home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-03-05 | 424.5 KB | 12,425 lines | [TEXT/MPS ] |
- {------------------------------------------------------------------------------
- #
- # Quill
- #
- # Apple Macintosh User Programming Group
- #
- # MultiFinder-Aware, AppleEvents-Aware Simple Styled TextEdit Sample Application
- #
- # by Bennet Marks
- #
- # Copyright © 1991 Apple Computer, Inc.
- #
- # Quill based on TEStyleSample (Copyright © 1989 Apple Computer, Inc.)
- #
- #
- # Quill.p - Pascal Source
- #
- # All rights reserved.
- #
- # Versions: 1.0 02/18/91
- #
- # Components: Quill.p
- # QuillGlue.a
- # Quill.r
- # Quill.h
- # Quill.make
- #
- # Quill is an example application that demonstrates the use
- # of the AppleEvent Manager in an application. It responds to a variety
- # of AppleEvents, including the Required AppleEvents (Open Application,
- # Quit Application, Open Documents, and Print Documents); it supports
- # the AppleEvents Object Model; and it is "factored", in the sense that
- # user actions (choosing a menu item, dragging a window, etc.) are translated
- # into AppleEvents that the application sends to itself, and then responds
- # to in much the way that it would respond to such events from an outside
- # source. Factoring your application is a way to make sure that all its
- # functionality (or at least as much as you want) is available through
- # AppleEvents. It also makes it easier to "record" user actions in the
- # form of AppleEvents.
- #
- # Quill is based on the sample application TEStyleSample, available
- # from Apple Computer. TEStyleSample was designed to demonstrate how
- # to initialize the commonly used toolbox managers, operate successfully
- # under MultiFinder, handle desk accessories and create, grow, and zoom windows.
- # Both styled and fundamental TextEdit toolbox calls and TextEdit autoscroll
- # are demonstrated. It also shows how to create and maintain scrollbar controls
- # as well as implementing a basic printing loop.
- #
- # In creating Quill, we have added in a number of application features
- # NOT found in TEStyleSample, including multiple windows, saving documents and
- # opeining saved documents, and the like. This was necessary to demonstrate how
- # to access these features from AppleEvents, but may come in handy in any case.
- # These added features are one of the reasons that Quill is a good deal
- # larger than TEStyleSample. Some of the extra code is present to implement
- # AppleEvent awareness, but a lot of it just handles the normal tasks that any
- # real application has to deal with. Don't be so worried.
- #
- # However, this application is an example of the form of an AppleEvent-aware
- # application; it is not a template. There's a lot more a real application
- # has to do, and much of it won't be demonstrated here.
- #
- # Quill is also a living document. We're still learning the best way
- # to do things with AppleEvents; and we're keeping one eye on the Open
- # Scripting Architecture and possible future scripting languages at
- # all times.
- #
- # Other sample apps you may want to look at are: TEStyleSample; TESample, a simpler
- # version of TEStyleSample without the styles; and Sample, a simple sample app
- # that doesn't use TextEdit or the Control Manager.
- #
- ------------------------------------------------------------------------------}
-
- {------------------------------------------------------------------------------
-
- HOW TO LOOK AT Quill: the routines are broken into two large groups.
- The first group are taken from TEStyleSample. Any major changes made for
- Quill are noted. The second group, starting from "NEW ROUTINES FOR
- QUILL", are, naturally, new routines for Quill. Some are
- completely new (including all the AppleEvents-specific routines), while others
- are major rewrites of old TEStyleSample routines (with new names), altered for
- AppleEvent awareness, more functionality, and more robustness. Sounds like coffee,
- doesn't it?
-
- IMPORTANT NOTE ON FACTORING AND OTHER DESIGN ISSUES: this sample program
- illustrates several techniques for dealing with and making use of AppleEvents.
- It is by no means the final word on the subject, and will probably evolve
- considerably. One example concerns "factoring" - that is, separating the user
- interface from the rest of the program, and designing the program so that user
- actions are translated into AppleEvents which the program then sends to itself.
- This is a useful strategy for making sure the full functionality of the program
- is available through AppleEvents, and it assists in the "recording" of user actions.
-
- In most cases I've taken each user action and translated it into a single,
- indivisible AppleEvent. For example, when the user chooses "Close" from the
- File Menu, the program may query her on whether to save or not, and if so to
- what file. It then takes all the information - what window to close, save/don't save,
- choice of file - attaches them to the Close event as parameters, and sends off
- the Close Event.
-
- THIS IS NOT THE ONLY "RIGHT" WAY TO DO THIS! You could, instead, query the
- user and then, if necessary, send TWO events - first the Save, then the Close.
- In this case the Close wouldn't be carrying around all those parameters.
-
- These design considerations will also affect what elements of the user interface
- would be included down in the event handlers. As a rule, it's best to design
- the event handlers so that they can operate without any user actions. After
- all, when AppleEvents are being used to run your program from a remote location,
- or a script, there may be no user available to respond.
-
- We will probably have more sample code to illustrate these different approaches
- in the future.
-
- A NOTE ON "GOTO'S": some purists may be surprised to see frequent use of GOTO
- in this code. Further examination, however, will reveal that in almost every
- case the only use of GOTO is in the form of GOTO 9, where 9 labels the location
- of the routine's clean-up code, where data structures are de-allocated, the function
- value is assigned, etc. If a serious error occurs, we jump to 9 to handle the
- clean-up; otherwise we just flow into it at the end of the routine.
-
- This is cleanly structured programming, despite the presence of the oft-dispised
- GOTO. In Pascal, the only alternative would be for each routine to have a
- CleanUp subroutine contained within it, to be called in place of each GOTO 9
- and at the end of the routine. Compared to the GOTO's, that's ugly, confusing,
- and (with our current compiler) generates very bad compiled code. Enough said?
-
- ------------------------------------------------------------------------------}
-
- {------------------------------------------------------------------------------
-
- MODIFICATION HISTORY
-
- 02/18/91 BHM New today
- 04/19/91 BHM Posted 1.00d2
- 04/22/91 BHM Added PropFromNullAccessor, CoerceObjToProp; typeMyProp;
- PropToken
- 05/14/91 BHM Added WordFromWndwAccessor, MyGetWord, ScanToBreak, ScanToNonBreak
- 05/15/91 BHM Added CoerceObjToText, GetTextProp
- 05/16/91 BHM (1) Introduced QuietCatchErr
- (2) Replaced CoerceObjToWndw, CoerceObjToProp, and
- CoerceObjToText with CoerceObjToAnything (pretty
- nifty, huh?)
- 05/20/91(!) BHM (1) Added CharFromWndwAccessor
- 05/21/91 BHM (1) Added MyGetTextElem, ScanToDelimiter, TextElemFromWndwAccessor
- 05/22/91 BHM **IMPORTANT** - switched to new file, NewAEQuillSample.p,
- to make text token changes and some OSL adjustments.
- AEQuillSample. still exists, plus a safety copy AEQuillSample.p.5.22
- 05/23/91 BHM Transferred over NewAEQuillSample.p, including all the changes in
- the text tokens, back to AEQuillSample.p, which lives again
- 05/24/91 BHM Added MakeStylTextDesc, CoerceStylTextToText
- 05/29/91 BHM Added GetTextElemFromText, MakeTextTokenForWndw, InitTextToken,
- TextElemFromTextAccessor, TextElemFromWndwAccessor; dropped
- CharFromWndwAccessor, WordFromWndwAccessor
- 05/31/91 BHM added "Quit NOW" menu command
- 06/03/91 BHM Started change-over to use of prop tokens; pre-change version
- saved as AEQuillSample.p.6.3
- 06/05/91 BHM Added MySetData, MyGetDataDesc, SetStylTextData, GetStylTextData,
- SetPropForWndwDesc, GetPropForWndwDesc. We now use prop tokens.
- 06/07/91 BHM Added CountWords, CountDelChars, CountTextElems
- 06/18/91 BHM over the last few days . . .
- (1) added GetPropForTextDesc, CoerceFontToInt, SetPropForText
- (2) added PropFromTextAccessor, MyGetUniformStyles, GetStyleFromConstant,
- MyAEListToStyles, InitTheStyles, StylesToAEList
- 06/21/91 BHM Added CoerceMyTextToStylText
- 07/01/91 BHM (1) Added lots of routines: SetUpEdit, DoMenuEdit, DoMenuStyle, HandleCopy,
- HandleCut, HandlePaste, MakeSelTextObj, SetFontForSelText, SetSizeForSelText,
- SetStyleForSelText, SelectTextToken, MyDoCut, MyDoPaste, MyDoCopy - and
- maybe a few more.
- (2) Also added new text element: "spots" (0-length strings)
- 07/09/91 BHM Added RealCountProc, HandleNumberOfElements
- 07/10/91 BHM (1) Added things for new ShowAllErrs property, including:
- globals gShowAllErrs, gInHandler; mathoms menu; routines
- PreHandler, PostHandler, SetPropForApp, GetPropForApp,
- DoMenuMathoms, PropFromAppAccessor
- (2) Improved the font stuff with: CoerceMyFontToText, CoerceMyFontToInt,
- CoerceMyFontToOldFont, CoerceTextToMyFont, CoerceIntToMyFont
- 07/15/91 BHM FIRST PROTOTYPE RELEASE
- 07/22/91 BHM Implemented dirty-window checking, with DirtyWindow, CleanWindow,
- WindowIsDirty
- 07/31/91 BHM (1) Put in code to handle window-switching as AppleEvents: BackWindow,
- HandleMove, MySendWindow, SendAEMove, MyBringWndwFront
- (2) Implemented recording of user typing actions: MyAEDoKey, StartKeyBuffering,
- ContinueKeyBuffering, CheckKeyBuffer, ResetKeyBuffer, InitKeyBufVals, InitKeyBuffer,
- GrowKeyBuffer, DestroyKeyBuffer, MakeTextRangeObj, MakeSpotObj - as well as new types
- (e.g. KeyBufferRecord), globals (keyBuffer), and constants to go with them
- (3) Took error dialog out of DoHighLevelEvent (so we don't complain when we get an
- AppleEvent we don't have a handler for; we just drop it)
- 08/02/91 BHM Put in support for text "style item" plain (including MakePlainList) -
- **CHECK - this should be cleaned up
- 08/05/91 BHM SECOND PROTOTYPE RELEASE
- 08/13/91 BHM Put in improved support for the formAbsoluteOrdinal naming form, making use
- of ordinary integers (positive or negative) and "magic ordinals" (first, last,
- any, middle, all). Routines: DecodeOrdinal (very handy), MakeWindowList,
- MyRandom, MakeElemList
- 08/18/91 BHM Put in support for some list handling, so the GetData and SetData can work
- with the lists of tokens that the OSL can produce. Routines: SetListData,
- GetListData, PropFromListAccessor
- 08/21/91 BHM (1) Replaced PropFromListAccessor with AnythingFromListAccessor (so we can get
- elements or properties from lists, returning lists as a result)
- (2) Put in new class: cListElem, which represents the elements in a list. Added
- ElemFromAnythingAccessor, and some code to MyCountProc, to handle them.
- 08/22/91 BHM (1) Put in pLength and pOffset for text tokens
- (2) Put in Kurt's Comparison routines (AECompareLib, and changes to MyCompareProc)
- 08/23/91 BHM THIRD PROTOTYPE RELEASE
- 08/26/91 BHM Added CoerceMyDocToMyWndw, other changes to handle and use cDocument (nearly identical
- in behavior to cWindow)
- 09/06/91 BHM Added HandleDeleteElement, with support routines: ExtendWord, ExtendTextElem, DeleteThisText,
- DeleteThisObj (all of which needs a lot more testing)
- 09/09/91 BHM Removed a lot of robustness checks from my accessors (particularly checks
- on containerClass) - they were starting to get in the way
- 09/16/91 BHM (1) Made some changes to handle token lists better: rewrote HandleGetData;
- added GetDataFromToken, GetDataFromTokenList; threw away GetListData,
- MyGetDataDesc
- (2) While I was at it, renamed GetPropForApp (now GetDataFromAppProp),
- GetPropForTextDesc (now GetDataFromTextProp), GetPropForWndwDesc (now
- GetDataFromWndwProp) - sounded better
- (3) Fonts are now of typeText and nothing else; there is no more typeFont,
- typeMyFont, or whatever. All the coercions for fonts have gone away.
- 09/18/91 BHM (1) Rewrote HandleSetData so that it would deal with lists better and allow
- the data to be specified by an object. Added SetDataForToken, SetDataForTokenList,
- GetSingularData; dropped MySetData, SetListData
- (2) Renamed SetPropForWndwDesc (now SetDataForWndwProp), SetPropForText (now
- SetDataForTextProp), SetPropForApp (now SetDataForAppProp)
- (3) Added code to return an error object descriptor to the caller when my use of
- the OSL results in an error. The major changes are in PostHandler. Also needed:
- global VAR gErrorDesc and new routine MyGetErrorDesc (a callback for the OSL).
- 10/04/91 BHM 10-4, Good Buddy! Put in "smart recording" of text operations - can now record
- "cut word 3" rather than "cut characters 14 to 19". New routines: SmartMakeSelTextObj,
- SmartTokenRep
- 12/11/91 BHM (1) Started changes for new Registry: proper use of kCoreEventClass (the 4 Required Events),
- kAECoreSuite (the Core Suite). Also corrected pName constant.
- (2) CHANGED NAME OF PROGRAM TO QUILL.
- 12/16/91 BHM (1) Changed HandleClose to: resolve direct obj directly (rather than in a coercion handler;
- work with lists of objects; handle kAEAsk option.
- (2) Changed all kAEAskUser ('asku') constants to kAEAsk ('ask ') to match new Registry.
- (3) Changed MyAECoerceDescPtr to handle typeWildCard properly (and to avoid unnecessary
- duplicating.
- 12/18/91 BHM Changed HandleMove to: resolve direct obj directly; handle lists; work with insertion locs.
- (And changed MyBringWndwFront to match.)
- 01/08/92 BHM Happy New Year! Implemented the new Registry version of text styles, using the typeTextStyles
- data type. This involved changes to SetDataForTextProp, GetDataFromTextProp, and InitTheStyles,
- and the addition of several new routines: StyleDescToStyleSets, ListToStyleSet,
- GetStyleItemFromConst, StyleSetToList, StyleSetsToStyleDesc, CoerceListOrValToTextStyles,
- SmartMakeStyleData (some of which replace previous routines). We now handle two text style
- properties: pTextStyles and pUniformStyles.
- 01/20/92 BHM Added AERegistry to USES, started integrating new constants, including:
- (1) Changed typeText to typeChar everywhere
- (2) Changed NumberOfElements to CountElements (in routine names, constants, etc.)
- (3) Changed typeRangeDataDescriptor to typeRangeDescriptor (**CHECK - how did that EVER work?)
- (4) Dropped SendAEMove (wasn't being used, didn't work with insertion locs - we use
- MyBringWndwFront instead)
- 01/21/92 BHM Replaced HandleNewElement with HandleCreateElement. Related to that: dropped SendAENewElement,
- rewrote DoMenuNew, fixed a bug in MySendWindow.
- 01/27/92 BHM (1) Put in code for typeIntlText (the default type for many text objects) - including
- CoerceStylTextToIntlText, CoerceIntlTextToText, CoerceTextToIntlText, TextToIntlText,
- IntlTextToText (there's a certain amount of overlap there).
- (2) HandleGetData now takes a list of requested types (instead of just one), and also
- deals with typeBest. Related: changes to GetDataFromTokenList, GetDataFromToken.
- New routines: GetWildTypes, MatchToReqList.
- (3) Changed event class on Cut, Copy, & Paste from kAECoreSuite to kAEMiscStandards
- 01/29/92 BHM (1) Rewrote HandlePrintDocs (now just HandlePrint) to handle obj specs that reolve to
- lists, and to get the interaction rules right. New routines: PrintFile (replacing
- MyPrintFile), PrintFileList, PrintToken (basically replacing MyPrintWindow), PrintTokenList,
- NewPrintText (replacing PrintText). New globals: gInterMode, gTriedDialog.
- 01/31/92 BHM (1) Rewrote HandleCopy, HandleCut, HandlePaste to match latest Registry (no parameters,
- always act on current selection); also DoMenuEdit. Dropped MyDoCopy, MyDoCut, MyDoPaste,
- SetUpEdit.
- (2) Added some window/document properties: pVisible, pIndex, pIsModal, pIsResizable,
- pHasTitleBar, pIsModified (note that I've extended all window props to documents and
- vice-versa)
- (3) Added HandleDoObjectsExist (an easy one)
- 02/13/92 BHM (1) Changed some constants that were peculiar to Quill - typeStylText, keyAETheStylInfo,
- typeStylInfo, keyAETheText - to their new, improved Registry-defined versions (from
- the Misc Standards) - typeStyledText, keyAEStyles, typeScrapStyles, keyAEText. Respectively.
- (2) Cleaned up a bug in SmartTokenRep (I was unlocking a potentially non-existent handle)
- 02/17/92 BHM (1) Added pUserSelection (app property) (also added MakeSelTextToken for it, a routine that should
- be used elsewhere as well - **CHECK)
- (2) Replaced pText with pContents (window property - all the text in the window), and made changes
- so that it works right - will now return same types as any other text object (not just typeChar)
- (3) Re-wrote TextTokenToDesc to eliminate silly dependencies; the new version is based on something
- once called GetTextProp (but which never did anything but get the text from a token; back then we
- didn't have any other text properties), which it replaces throughout (meaning, in MakeStylTextDesc)
- (4) Made an EXPERIMENTAL change wherein the pContents property of windows/docs is returned as
- a text token (rather than a window prop token), in order to net us all the text properties/behaviors
- for free. Gearing up to do the same for pUserSelection, although that's a little more complicated
- (**CHECK)
- 02/19/92 BHM (1) Fixed bug in GetDataFromTextProp (pTextStyles case) that was skipping over the offStyles
- (2) Replaced kAECondense with kAECondensed, kAEExtend with kAEExpanded (constants representing
- text style items; I had been using my own for those two, but they're in the Registry)
- 02/21/92 BHM Restored optional text object parameters to Cut, Copy, and Paste events so that they'll record
- better. This involved bringing back SetUpEdit, MyDoCut, MyDoCopy, and MyDoPaste; changes to
- the three event handlers; and some other minor alterations
-
-
- END OF HISTORY
-
- ------------------------------------------------------------------------------}
-
- PROGRAM Quill;
-
- {Segmentation strategy:
-
- This program consists of three segments. Main contains most of the code,
- including the MPW libraries, and the main program. Initialize contains
- code that is only used once, during startup, and can be unloaded after the
- program starts. %A5Init is automatically created by the Linker to initialize
- globals for the MPW libraries and is unloaded right away.}
-
-
- {SetPort strategy:
-
- Toolbox routines do not change the current port. In spite of this, in this
- program we use a strategy of calling SetPort whenever we want to draw or
- make calls which depend on the current port. This makes us less vulnerable
- to bugs in other software which might alter the current port (such as the
- bug (feature?) in many desk accessories which change the port on OpenDeskAcc).
- Hopefully, this also makes the routines from this program more self-contained,
- since they don't depend on the current port setting.}
-
-
- {Clipboard strategy:
-
- Under styled TextEdit, TECut and TECopy will write both the text and associated
- style information directly to the desk scrap as types 'TEXT' and 'styl'.
- Instead of using TEToScrap and TEFromScrap, a new routine TEStylPaste, will
- transfer the text and style from the desk scrap to the document. }
-
- {Error-handling strategy (NEW FOR QUILL):
-
- All AppleEvent Manager routines are functions that return an error code. In
- keeping with this philosophy, most of the new routines in Quill also
- return error codes. Error-handling is done in a very general way, designed for
- clarity and ease of debugging - NOT for true user-oriented error-handling.
-
- Every place in the code where a serious error may occur (one that would require
- aborting some activity and/or informing the user) there is a call to one of the
- three slightly different error-checking routines: CatchErr, CheckErr, and DoMyErr.
- Right now all 3 are set up to display a dialog window giving the error number
- and the place in the code where it occurred (some unique number supplied by the
- programmer), and then return to the program. They could just as easily be set up
- to: enter the debugger; write a string to a file; beep a tune; or whatever else
- you want. In a real application, you would want to do different things depending
- on the location and nature of the error. All routines are self-cleaning: if an
- error occurs (and CatchErr et al return to the program after reporting it, as they do
- now), the routine will dispose of structures it's created, unlock handles it's locked,
- etc., as appropriate. In most cases it will also pass the error up the routine that
- called it, so most serious errors will trigger a "chain" of dialog alerts as the
- error gets passed up the calling chain. Again, you can change this behavior in
- whichever way suits you.
-
- Most of my AppleEvent "Sends" do not ask for a reply, and thus they do not react
- to any errors generated by the event handlers. However, if you DO ask for a reply,
- and a handler happens to generate an error, it will return the error code as part of
- the reply - this is done automatically by the AE Manager. (As currently written, the
- handlers will NOT return an error string, which has to be done explicitly.) In a real
- application, most of the visible error-handling - alerting the user, for example -
- would probably be done by the code that sends the events, not the handlers that receive
- them. }
-
-
-
- {$D+}
-
- USES
- MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf, Traps, AppleEvents,
- AEObjects, AECompareLib, MacPrint, AERegistry, Script, Language, OSUtils;
-
- CONST
-
- {kTextMargin is the number of pixels we leave blank at the edge of the window.}
- kTextMargin = 2;
-
- {kMaxOpenDocuments is used to determine whether a new document can be opened
- or created. We keep track of the number of open documents, and disable the
- menu items that create a new document when the maximum is reached. If the
- number of documents falls below the maximum, the items are enabled again.}
- kMaxOpenDocuments = 6; { NEW FOR QUILL }
-
- {kMaxDocWidth is an arbitrary number used to specify the width of the TERec's
- destination rectangle so that word wrap and horizontal scrolling can be
- demonstrated.}
- kMaxDocWidth = 576;
-
- {kMinDocDim is used to limit the minimum dimension of a window when GrowWindow
- is called.}
- kMinDocDim = 64;
-
- {kControlInvisible is used to 'turn off' controls (i.e., cause the control not
- to be redrawn as a result of some Control Manager call such as SetCtlValue)
- by being put into the contrlVis field of the record. kControlVisible is used
- the same way to 'turn on' the control.}
- kControlInvisible = 0;
- kControlVisible = $FF;
-
- {kScrollBarAdjust and kScrollBarWidth are used in calculating
- values for control positioning and sizing.}
- kScrollbarWidth = 16;
- kScrollbarAdjust = kScrollbarWidth - 1;
-
- {kScrollTweek compensates for off-by-one requirements of the scrollbars
- to have borders coincide with the growbox.}
- kScrollTweek = 2;
-
- {kCrChar is used to match with a carriage return when calculating the
- number of lines in the TextEdit record. kDelChar is used to check for
- delete in keyDowns.}
- kCRChar = 13;
- kDelChar = 8;
-
- {kButtonScroll is how many pixels to scroll horizontally when the button part
- of the horizontal scrollbar is pressed.}
- kButtonScroll = 4;
-
- {kMaxTELength is an arbitrary number used to limit the length of text in the TERec
- so that various errors won't occur from too many characters in the text.}
- kMaxTELength = 32000;
- (* what about that tech note I wrote? is this a valid check anymore? maw *)
-
- {kSysEnvironsVersion is passed to SysEnvirons to tell it which version of the
- SysEnvRec we understand.}
- kSysEnvironsVersion = 1;
-
- {kOSEvent is the event number of the suspend/resume and mouse-moved events sent
- by MultiFinder. Once we determine that an event is an osEvent, we look at the
- high byte of the message sent to determine which kind it is. To differentiate
- suspend and resume events we check the resumeMask bit.}
- kOSEvent = app4Evt; { event used by MultiFinder }
- kSuspendResumeMessage = 1; { high byte of suspend/resume event message }
- kResumeMask = 1; { bit of message field for resume vs. suspend }
- kMouseMovedMessage = $FA; { high byte of mouse-moved event message }
- kNoEvents = 0; {no events mask}
-
- {kMinHeap - This is the minimum result from the following
- equation:
-
- ORD(GetApplLimit) - ORD(ApplicZone)
-
- for the application to run. It will insure that enough memory will
- be around for reasonable-sized scraps, FKEYs, etc. to exist with the
- application, and still give the application some 'breathing room'.
- To derive this number, we ran under a MultiFinder partition that was
- our requested minimum size, as given in the 'SIZE' resource.}
-
- kMinHeap = 29 * 1024;
-
- {kMinSpace - This is the minimum result from PurgeSpace, when called
- at initialization time, for the application to run. This number acts
- as a double-check to insure that there really is enough memory for the
- application to run, including what has been taken up already by
- pre-loaded resources, the scrap, code, and other sundry memory blocks.}
-
- kMinSpace = 20 * 1024;
-
- {kExtremeNeg and kExtremePos are used to set up wide open rectangles and regions.}
- kExtremeNeg = -32768;
- kExtremePos = 32767 - 1; { required for old region bug }
-
- {kTESlop provides some extra security when pre-flighting edit commands.}
- kTESlop = 1024;
-
- {kErrStrings is the resource ID for the error strings STR# resource.}
- kErrStrings = 128;
-
- kNumOfStyles = 7; { see InitTheStyles for the list }
-
- { The following are indicies into STR# resources. }
- eWrongMachine = 1;
- eSmallSize = 2;
- eNoMemory = 3;
- eNoSpaceCut = 4;
- eNoCut = 5;
- eNoCopy = 6;
- eExceedPaste = 7;
- eNoSpacePaste = 8;
- eNoWindow = 9;
- eExceedChar = 10;
- eNoPaste = 11;
- eNoSelfAddr = 12; { NEW FOR QUILL }
-
-
- { The following constants are all resource IDs, corresponding to their resources }
-
- rMenuBar = 128; { application's menu bar }
- rAboutAlert = 128; { about alert }
- rUserError = 129; { user error alert }
- rUserAlert = 130; { user alert }
- rYesOrNo = 131; { yes/no/cancel window }
- rDocWindow = 128; { application's window }
-
- rVScroll = 128; { vertical scrollbar control }
- rHScroll = 129; { horizontal scrollbar control }
-
-
- { The following constants are all menu and item IDs corresponding to their resources }
-
- mApple = 128; { Apple menu }
- iAbout = 1;
-
- mFile = 129; { File menu }
- iNew = 1;
- iOpen = 2;
- iClose = 4;
- iSave = 5; { NEW FOR QUILL }
- iSaveAs = 6; { NEW FOR QUILL }
- iRevert = 7; { NEW FOR QUILL }
-
- iPageSetup = 9; { NEW FOR QUILL }
- iPrint = 10; { NEW FOR QUILL }
- iPrintFile = 11; { NEW FOR QUILL }
- iQuit = 13;
- iQuitNow = 14; { NEW FOR QUILLSAMPLE }
-
- mEdit = 130; { Edit menu }
- iUndo = 1;
- iCut = 3;
- iCopy = 4;
- iPaste = 5;
- iClear = 6;
- iSelectAll = 8; { Added for TEStyleSample }
-
- mFont = 131; { Font menu-added for TEStyleSample }
-
- mFontSize = 132; { Font size menu-added for TEStyleSample }
- iNine = 1;
- iTen = 2;
- iTwelve = 3;
- iFourteen = 4;
- iEighteen = 5;
- iTwoFour = 6;
-
- mStyle = 133; { Style menu-added for TEStyleSample }
- iPlain = 1;
- iBold = 3;
- iItalic = 4;
- iUnderline = 5;
- iOutline = 6;
- iShadow = 7;
-
- mMathoms = 134;
- iShowAllErrs = 1;
-
- {kDITop and kDILeft are used to locate the Disk Initialization dialogs.}
- kDITop = $0050;
- kDILeft = $0070;
-
-
- { the following constants re all NEW FOR QUILL }
-
- typeMyWndw = 'BWIN'; { my private token type for windows }
- typeMyDoc = 'BDOC';
- typeMyProp = 'BPRP'; { my private token type for properties }
- typeMyText = 'BTXT'; { my private token type for text }
-
- typeMyWndwProp = 'BWDP'; { later we may want to go to typeMyProp }
- typeMyTextProp = 'BTXP';
- typeMyAppProp = 'BAPR';
-
- badVRefNum = $7FFF; { no volume should ever get this vRefNum }
-
-
- { these are temporary, while we decide what kind
- of errors callbacks should return }
- genericErr = -1799;
- accessorErr = -1798;
- countProcErr = -1797;
- compareErr = -1796;
-
- errTooManyDocs = -1795;
- errNoNewWindow = -1794;
- errNoNewControl = -1793;
- errNoNewTE = -1792;
- stylHndlErr = -1791;
-
- errAEUserCancelled = -1790;
-
- errAEBadData = -1789;
- errCantPaste = -1788;
-
- errAENeedSingleItem = -1787;
-
- errAEMiscPrintErr = -1786;
-
- asciiSpace = $20;
- asciiCR = $0D;
- asciiComma = $2C;
-
- { codes for arrow keys }
- kRightArrow = $1D;
- kLeftArrow = $1C;
- kUpArrow = $1E;
- kDownArrow = $1F;
-
- kBufStartSize = 64;
- kBufGrowAmount = 64;
-
-
- { these should come from the registry }
-
- { kAECoreSuite = 'core';}
-
-
- { cNull = typeNull; }{ combine the redundancies . . . }
- { cWindow = 'cwin';
- typeText = 'TEXT';
- cText = typeChar;
- pText = 'TEXT';
- cWord = 'cwor';
-
- cDocument = 'docu';
-
- cProperty = 'prop';
-
- kAESetData = 'setd';
- keyAETheData = 'kdat';
- cQDRectangle = 'qdrt';
- typeQDRectangle = cQDRectangle;
- pBounds = 'pbnd';
- pName = 'pnam';
-
- pPosition = 'ppos';
- typeQDPoint = 'QDpt';
- cQDPoint = typeQDPoint;
-
-
- keyAESaveOptions = 'savo';
- kAEClose = 'clos';
- kAEYes = 'yes ';
- kAENo = 'no ';
- kAEAsk = 'ask ';
-
- keyAEObjToCreate = 'obtc';
- kAENewElement = 'nobj';
-
- keyAEDestination = 'dest';
-
- kAESave = 'save';
-
- kAEGetData = 'getd';
-
- keyAERequestedType = 'rtyp';
-
- pVersion = 'vers';
-
- cChar = 'cha ';
- cLine = 'clin';
- cItem = 'citm';
- cSpot = 'cspt';
-
- cListElem = 'celm';
-
-
-
- typeRangeDataDescriptor = 'rdd ';
-
- pPointSize = 'ptsz';
- typeFixed16 = 'fixd';
-
- pFont = 'font';
-
- pTextStyles = 'txst';
- pUniformStyles = 'ustl';
-
- pLength = 'lgth';
- pOffset = 'ofst';
-
- kAEBold = 'bold';
- kAENotBold = 'nbld';
- kAEItalic = 'ital';
- kAENotItalic = 'nitl';
- kAEUnderline = 'ulin';
- kAENotUnderline = 'nuln';
- kAEOutline = 'olin';
- kAENotOutline = 'noln';
- kAEShadow = 'shdw';
- kAENotShadow = 'nsdw';
- kAECondense = 'cnds';
- kAENotCondense = 'ncnd';
- kAEExtend = 'xtnd';
- kAENotExtend = 'nxtn';
-
- kAEPlain = 'plai';
-
- kAECut = 'cut ';
- kAEPaste = 'past';
- kAECopy = 'copy'; }{ **CHECK - registry says something different (and weird) }
-
- { kAENumberOfElements = 'nele';}
- { keyAEWantClass = 'want';}
- { keyAEObjectClass = 'kocl';
-
- pErrMode = 'pemd';
- kShowAllErrs = 'sars';
- kShowFewErrs = 'sfrs';
-
- kAEMove = 'move';
- typeInsertionLoc = 'insl';
-
- keyAEPosition = 'kpos';
- keyAEObject = 'kobj';
-
- kAEBefore = 'befo';
- kAEAfter = 'afte';
- kAEReplace = 'rplc';
-
- kAEBeginning = 'bgng';
- kAEEnd = 'end ';
-
- keyAEInsertHere = 'insr';
- keyAEWhereModifier = 'wher';
-
- kAEDontExecute = $2000;} { use in SendMode, when you just want an event recorded, not executed }
-
- { kAEDelete = 'delo';
-
- keyAEErrorObject = 'erob';
-
- keyAEOnStyles = 'onst';
- keyAEOffStyles = 'ofst';
- typeTextStyles = 'tsty';}
-
- cListElem = 'celm';
-
- kAEDontExecute = $2000;
-
-
- cSpot = 'cspt';
-
- pErrMode = 'pemd';
- kShowAllErrs = 'sars';
- kShowFewErrs = 'sfrs';
-
- pLength = 'lgth';
- pOffset = 'ofst';
-
- pContents = 'pcnt';
-
- pPosition = 'ppos';
-
-
-
- { these next are for New Element - need to be replaced with Create Object }
- keyAEObjToCreate = 'obtc';
- kAENewElement = 'nobj';
-
- cNull = typeNull;
-
- { do we want/need these? }
- kAECondense = 'cnds';
- kAEExtend = 'xtnd';
-
- keyAEErrorObject = 'erob';
-
- { END OF CONSTANTS }
-
-
- TYPE
- {A DocumentRecord contains the WindowRecord for one of our document windows,
- as well as the TEHandle for the text we are editing. We have added fields to
- hold the ControlHandles to the vertical and horizontal scrollbars and to hold
- the address of the default clikLoop that gets attached to a TERec when you call
- TEAutoView. Other document fields can be added to this record as needed. For
- a similar example, see how the Window Manager and Dialog Manager add fields
- after the GrafPort.}
- DocumentRecord = RECORD
- docWindow: WindowRecord;
- docTE: TEHandle;
- docVScroll: ControlHandle;
- docHScroll: ControlHandle;
- docClik: ProcPtr;
- docFile: FSSpec; { NEW FOR QUILL; holds file spec for doc, if any }
- dirtyFlag: BOOLEAN; { NEW FOR QUILL }
- END;
- DocumentPeek = ^DocumentRecord;
-
- HandleList = ARRAY[1..256] OF Handle; { declared with 256 to beat range-checking }
- { local versions can be declared with less }
- HandleListPtr = ^HandleList;
-
- WndwPropToken =
- RECORD
- wpWndw: WindowPtr;
- wpProp: DescType;
- END;
-
- TextToken =
- RECORD
- tokenClass: DescType; { cChar, cWord, cClass, or cLine } { or cSpot }
- tokenWndw: WindowPtr;
- tokenOffset: LongInt; { offset from start of text to first character of token }
- tokenLength: LongInt; { length of token }
- END;
-
- { NOTES: offsets start at 0; e.g., tokenOffset = 0 and tokenLength = 1
- describes the first character of the text }
-
- TextPropToken =
- RECORD
- tpText: TextToken;
- tpProp: DescType;
- END;
-
- StyleNameRec =
- RECORD
- snStylItem: StyleItem;
- snName: Str15;
- END;
-
- MyStylItemRec =
- RECORD
- stylItem: StyleItem;
- stylConst: DescType;
- END;
-
- CharBuffer = PACKED ARRAY[0..kMaxTELength] OF CHAR;
- CharBufPtr = ^CharBuffer;
- CharBufHandle = ^CharBufPtr;
-
- KeyBufferRecord =
- RECORD
- bufEmpty: BOOLEAN;
- bufSize: INTEGER;
- bufCharCount: INTEGER;
- bufDelCount: INTEGER;
- bufSelStart: INTEGER;
- bufSelEnd: INTEGER;
- bufWndw: WindowPtr;
- bufChars: CharBufHandle;
- bufDesc: AEDesc;
- END;
-
- { END OF TYPES }
-
- VAR
- {The "g" prefix is used to emphasize that a variable is global.}
- gMac : SysEnvRec; { set up by Initialize }
- gHasWaitNextEvent : BOOLEAN; { set up by Initialize }
- gInBackground : BOOLEAN; { maintained by Initialize and DoEvent }
- gNumDocuments : INTEGER; { maintained by Initialize, MyNewWindow, and DoMenuClose }
- gDocCount: INTEGER; { total number of windows open since startup }
-
- {New globals to support printing and style selection }
- gTxStyle : TextStyle; { holds style selected, plain default, maintained by DoMenuCommand }
- gFontName : Str255; { name of font selected, app font default, maintained by DoMenuCommand }
- gFontID : INTEGER; { ID of font selected, app font default, maintained by DoMenuCommand }
- gFontSize : LONGINT; { font size selected, 12 pt default, maintained by DoMenuCommand }
- gPrinterRecord : THPrint; { print handle, maintained by NewPrintText }
- gPrinterPort : TPPrPort; { pointer to Print Manager's GrafPort }
-
- { the following globals are all NEW FOR QUILL }
-
- gTempBool: BOOLEAN;
- gTempPtr: Ptr;
- gTempLong: LongInt;
- gTempInt: INTEGER;
- gTempType: DescType;
-
- gActSize: Size;
- gReturnedType: DescType;
-
- gQuitNow: BOOLEAN;
- gProcPtr: EventHandlerProcPtr;
-
- gNullDesc: AEDesc; { initialized in Initialize, disposed of in Terminate }
- gSelfAddrDesc: AEAddressDesc; { initialized in Initialize, disposed of in Terminate }
-
- gIndex: INTEGER;
-
- theStyles: ARRAY[1..kNumOfStyles] OF MyStylItemRec;
- gAllStyles: Style;
-
-
- gReturnedKeywd: AEKeyWord;
-
- gInHandler: BOOLEAN;
- gShowAllErrs: BOOLEAN; { TRUE to show all error dialogs; if FALSE, then error dialogs }
- { will not be displayed from withing AppleEvent handlers. Other }
- { routines, however - including the ones that send AppleEvents - }
- { will still put up error dialogs }
-
- keyBuffer: KeyBufferRecord;
-
- gErrorDesc: AEDesc;
-
- gInterMode: LongInt;
- gTriedDialog: BOOLEAN;
-
- { END OF GLOBAL VARS }
-
-
- { START OF FORWARD REFERENCES }
-
- { EVENT HANDLERS }
- FUNCTION HandleClose(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleCopy(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleCreateElement(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleDeleteElement(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleDoObjectsExist(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleCut(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleGetData(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleMove(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleCountElements(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleOpenApp(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleOpenDocs(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandlePrint(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandlePaste(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleQuitApp(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleSave(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION HandleSetData(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
-
- { OTHER AE CALLBACKS }
- FUNCTION AnythingFromListAccessor(wantClass: DescType; container: AEDesc;
- containerClass: DescType; form: DescType; selectionData: AEDesc;
- VAR value: AEDesc; theRefCon: LongInt): OSErr; FORWARD;
- FUNCTION CoerceListOrValToTextStyles(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION CoerceMyDocToMyWndw(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION CoerceMyTextToStylText(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION CoerceObjToAnything(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION CoerceStylTextToIntlText(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION CoerceStylTextToText(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION CoerceTextToIntlText(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION ElemFromAnythingAccessor(wantClass: DescType; container: AEDesc;
- containerClass: DescType; form: DescType; selectionData: AEDesc;
- VAR value: AEDesc; theRefCon: LongInt): OSErr; FORWARD;
- FUNCTION MyCompareProc(oper: DescType; obj1: AEDesc; obj2: AEDesc;
- VAR result: BOOLEAN): OSErr; FORWARD;
- FUNCTION MyCountProc(desiredType: DescType; containerClass: DescType;
- container: AEDesc; VAR result: LongInt): OSErr; FORWARD;
- FUNCTION MyGetErrorDesc(VAR result: DescPtr): OSErr; FORWARD;
- FUNCTION PropFromAppAccessor(wantClass: DescType; container: AEDesc ;
- containerClass: DescType; form: DescType; selectionData: AEDesc;
- VAR value: AEDesc; theRefCon: LongInt): OSErr; FORWARD;
- FUNCTION PropFromTextAccessor(wantClass: DescType; container: AEDesc ;
- containerClass: DescType; form: DescType; selectionData: AEDesc;
- VAR value: AEDesc; theRefCon: LongInt): OSErr; FORWARD;
- FUNCTION PropFromWndwAccessor(wantClass: DescType; container: AEDesc ;
- containerClass: DescType; form: DescType; selectionData: AEDesc;
- VAR value: AEDesc; theRefCon: LongInt): OSErr; FORWARD;
- FUNCTION TextElemFromTextAccessor(wantClass: DescType; container: AEDesc ;
- containerClass: DescType; form: DescType; selectionData: AEDesc; VAR value: AEDesc;
- theRefCon: LongInt): OSErr; FORWARD;
- FUNCTION TextElemFromWndwAccessor(wantClass: DescType; container: AEDesc ;
- containerClass: DescType; form: DescType; selectionData: AEDesc; VAR value: AEDesc;
- theRefCon: LongInt): OSErr; FORWARD;
- FUNCTION WndwFromNullAccessor(wantClass: DescType; container: AEDesc ;
- containerClass: DescType; form: DescType; selectionData: AEDesc;
- VAR value: AEDesc; theRefCon: LongInt): OSErr; FORWARD;
-
- { AE UTILITIES }
- FUNCTION DisposeSomeDescs(desc1Ptr, desc2Ptr, desc3Ptr,
- desc4Ptr, desc5Ptr: DescPtr): OSErr; FORWARD;
- FUNCTION GetInteractMode(theAppleEvent: AppleEvent;
- VAR interMode: LongInt): OSErr; FORWARD;
- FUNCTION GetObjSpecFields(theObjSpec: AEDesc; VAR theClass: DescType;
- VAR theCont: AEDesc; VAR theKeyForm: AEKeyword;
- VAR theKeyData: AEDesc): OSErr; FORWARD;
- FUNCTION GotRequiredParams(theAppleEvent: AppleEvent): OSErr; FORWARD;
- PROCEDURE InitAEHandlers; FORWARD;
- PROCEDURE InitSomeDescs(desc1Ptr, desc2Ptr, desc3Ptr,
- desc4Ptr, desc5Ptr: DescPtr); FORWARD;
- FUNCTION MakeInsertionLoc(relObj: AEDesc; position: DescType;
- VAR insertionLoc: AEDesc): OSErr; FORWARD;
- FUNCTION MakeObjSpec(desiredClass: DescType; theCont: AEDesc;
- keyForm: DescType; keyDataType: DescType; keyDataPtr: Ptr;
- keyDataSize: Size; VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION MakeObjSpecFromIndex(desiredClass: DescType; theCont: AEDesc;
- index: LongInt; VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION MakeObjSpecFromName(desiredClass: DescType; theCont: AEDesc;
- name: Str255; VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION MakeObjSpecFromRange(desiredClass: DescType; theCont: AEDesc;
- startObj: AEDesc; stopObj: AEDesc; VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION MakePlainList(VAR plainList: AEdesc): OSErr; FORWARD;
- FUNCTION MakePropObjSpec(theObj: AEDesc; theProp: DescType;
- VAR result: AEDesc): OSErr; FORWARD;
- FUNCTION MakeSelfAddr(VAR addrDesc: AEAddressDesc): OSErr; FORWARD;
- FUNCTION MakeSelTextObj(window: WindowPtr; VAR selTextObj: AEDesc): OSErr; FORWARD;
- PROCEDURE MakeSelTextToken(window: WindowPtr; VAR selTextToken: TextToken); FORWARD;
- FUNCTION MakeSpotObj(wndwIndex: INTEGER; spotIndex: INTEGER;
- VAR spotObj: AEDesc): OSErr; FORWARD;
- FUNCTION MakeStylTextDesc(myTextToken: TextToken; VAR theSTDesc: AEDesc): OSErr; FORWARD;
- FUNCTION MakeTextRangeObj(wndwIndex: INTEGER; startChar: INTEGER;
- endChar: INTEGER; VAR rangeObj: AEDEsc): OSErr; FORWARD;
- FUNCTION MightWeInteract(interMode: LongInt; VAR mayInteract: BOOLEAN): OSErr; FORWARD;
- FUNCTION MyAEChangeDescType(VAR theDesc: AEDesc; newType: DescType): OSErr; FORWARD;
- FUNCTION MyAECoerceDescPtr(theAEDesc: AEDesc; toType: DescType; dataPtr: Ptr;
- maximumSize: Size; VAR actualSize: Size): OSErr; FORWARD;
- FUNCTION TextDescToStr(textDesc: AEDesc; VAR destStr: Str255;
- VAR actSize: Size): OSErr; FORWARD;
- FUNCTION SmartMakeSelTextObj(window: WindowPtr; VAR selTextObj: AEDesc): OSErr; FORWARD;
- FUNCTION SmartTokenRep(myToken: TextToken; VAR smartDesc: AEDesc): OSErr; FORWARD;
- FUNCTION StrToTextDesc(srcStr: Str255; VAR textDesc: AEDesc): OSErr; FORWARD;
-
- { MENU ACTIONS }
- PROCEDURE DoMenuClose(window: WindowPtr); FORWARD;
- PROCEDURE DoMenuEdit(window: WindowPtr; editCode: INTEGER); FORWARD; { Cut, Copy, & Paste }
- PROCEDURE DoMenuMathoms(menuItem: INTEGER); FORWARD;
- PROCEDURE DoMenuNew; FORWARD;
- PROCEDURE DoMenuOpen; FORWARD;
- PROCEDURE DoMenuPrint; FORWARD;
- PROCEDURE DoMenuPrintFile; FORWARD;
- PROCEDURE DoMenuQuit; FORWARD;
- PROCEDURE DoMenuQuitNow; FORWARD;
- PROCEDURE DoMenuSave(window: WindowPtr); FORWARD;
- PROCEDURE DoMenuSaveAs(window: WindowPtr); FORWARD;
- PROCEDURE DoMenuStyle(window: WindowPtr; menuItem: INTEGER); FORWARD;
-
- { SENDING APPLEEVENTS }
- PROCEDURE SendAEClose(window: WindowPtr; saveFlag, fileParamFlag: BOOLEAN;
- fileSpec: FSSpec); FORWARD;
- PROCEDURE SendAEOpenDoc(myFSSpec: FSSpec); FORWARD;
- PROCEDURE SendAEPrintDoc(docDesc: AEDesc; doInteract: BOOLEAN); FORWARD;
- PROCEDURE SendAEQuit(saveOpt: DescType); FORWARD;
- PROCEDURE SendAESave(window: WindowPtr; fileParamFlag: BOOLEAN;
- fileSpec: FSSpec); FORWARD;
- PROCEDURE SendAESetObjProp(theObj: AEDesc; theProp: DescType; theData: AEDesc); FORWARD;
- PROCEDURE SendAESetWndwPos(index: INTEGER; thePos: Point); FORWARD;
- PROCEDURE SendAESetWndwRect(index: INTEGER; theRect: Rect); FORWARD;
-
- { USER PROMPTS FOR FILES }
- FUNCTION AskAboutSave(name: Str255; VAR saveFlag: BOOLEAN): BOOLEAN; FORWARD;
- FUNCTION AskBeforeClosing(window: WindowPtr; VAR saveFlag: BOOLEAN;
- VAR docFileGood: BOOLEAN; VAR fileSpec: FSSpec): BOOLEAN; FORWARD;
- FUNCTION AskForFile(name: Str255; VAR fileSpec: FSSpec): BOOLEAN; FORWARD;
- FUNCTION AskUser( question: Str255 ): INTEGER; FORWARD;
-
- { SOME IMPORTANT ACTIVITIES }
- FUNCTION DecodeOrdinal(ordData: AEDesc; count: LongInt; VAR index: LongInt;
- VAR allFlag: BOOLEAN; VAR zeroFlag: BOOLEAN): OSErr; FORWARD;
- FUNCTION DeleteThisObj(myObj: AEDesc): OSErr; FORWARD;
- FUNCTION GetDataFromAppProp(appPropDesc: AEDesc;
- VAR propDataDesc: AEDesc): OSErr; FORWARD;
- FUNCTION GetDataFromToken(myToken: AEDesc; reqTypesList: AEDesc;
- VAR dataDesc: AEDesc; VAR notToken: BOOLEAN): OSErr; FORWARD;
- FUNCTION GetDataFromTokenList(myList: AEDesc; reqTypesList: AEDesc;
- VAR dataList: AEDesc): OSErr; FORWARD;
- FUNCTION GetSingularData(srcDesc: AEDesc; reqType: DescType;
- VAR dataDesc: AEDesc): OSErr; FORWARD;
- FUNCTION GetStylTextData(textDesc: AEDesc; VAR dataDesc: AEDesc): OSErr; FORWARD;
- FUNCTION GetWildTypes(myToken: AEDesc; VAR bestType: DescType;
- VAR defType: DescType): OSErr; FORWARD;
- FUNCTION MatchToReqList(srcDesc: AEDesc; reqList: AEDesc; bestType: DescType;
- defType: DescType; VAR dstDesc: AEDesc): OSErr; FORWARD;
- FUNCTION MyNewWindow(VAR window: WindowPtr): OSErr; FORWARD;
- FUNCTION MyOpenWindow(myFSSpec: FSSpec): OSErr; FORWARD;
- FUNCTION NewPrintText( hTE : TEHandle; useDialog: BOOLEAN ): OSErr; FORWARD;
- FUNCTION PrintFile(myFSS: FSSpec): OSErr; FORWARD;
- FUNCTION PrintFileList(theList: AEDesc): OSErr; FORWARD;
- PROCEDURE PostHandler(reply: AppleEvent; errNum: OSErr); FORWARD;
- PROCEDURE PreHandler; FORWARD;
- FUNCTION RealCountProc(desiredType: DescType; container: AEDesc;
- VAR result: LongInt): OSErr; FORWARD;
- FUNCTION SetDataForAppProp(appPropDesc: AEDesc; propDataDesc: AEDesc): OSErr; FORWARD;
- FUNCTION SetDataForToken(myToken: AEDesc; dataDesc: AEDesc): OSErr; FORWARD;
- FUNCTION SetDataForTokenList(myList: AEDesc; dataDesc: AEDesc): OSErr; FORWARD;
- FUNCTION SetStylTextData(textDesc: AEDesc; dataDesc: AEDesc): OSErr; FORWARD;
- FUNCTION SetUpEdit(theAppleEvent: AppleEvent; VAR window: WindowPtr): OSErr; FORWARD;
-
-
- { TERMINATION ROUTINES }
- FUNCTION CloseAllAskUser(VAR userCancelled: BOOLEAN): OSErr; FORWARD;
- PROCEDURE CloseAllNoSave; FORWARD;
- FUNCTION CloseAllWithSave: OSErr; FORWARD;
- FUNCTION MyTerminate(saveOpt: DescType; VAR userCancelled: BOOLEAN): OSErr; FORWARD;
- FUNCTION SmartCloseAll(saveOpt: DescType; VAR userCancelled: BOOLEAN): OSErr; FORWARD;
-
- { WINDOW INFO & HANDLING }
- FUNCTION BackWindow: WindowPtr; FORWARD;
- PROCEDURE CleanWindow(window: WindowPtr); FORWARD;
- FUNCTION CountWindows: INTEGER; FORWARD;
- PROCEDURE DirtyWindow(window: WindowPtr); FORWARD;
- PROCEDURE DoDragWindow(theWindow: WindowPtr; startPt: Point; boundsRect: Rect); FORWARD;
- FUNCTION GetDataFromWndwProp(wndwPropDesc: AEDesc;
- VAR propDataDesc: AEDesc): OSErr; FORWARD;
- FUNCTION GetWindowProp(window: WindowPtr; theProp: DescType;
- VAR dataDesc: AEDesc): OSErr; FORWARD;
- FUNCTION IndexFromWndwPtr(window: WindowPtr): INTEGER; FORWARD;
- FUNCTION MakeWindowList(VAR wndwList: AEDesc; myType: DescType): OSErr; FORWARD;
- PROCEDURE MyBringWndwFront(window: WindowPtr); FORWARD;
- FUNCTION MySendWindow(aWindow: WindowPtr; bWindow: WindowPtr;
- whereMod: DescType): OSErr; FORWARD;
- FUNCTION SetWindowProp(window: WindowPtr; theProp: DescType;
- propData: AEDesc): OSErr; FORWARD;
- FUNCTION SetDataForWndwProp(wndwPropDesc: AEDesc; propDataDesc: AEDesc): OSErr; FORWARD;
- PROCEDURE ShutTheWindow(window: WindowPtr); FORWARD;
- FUNCTION WindowIsDirty(window: WindowPtr): BOOLEAN; FORWARD;
- FUNCTION WndwPtrFromIndex(index: INTEGER): WindowPtr; FORWARD;
- FUNCTION WndwPtrFromName(name: Str255): WindowPtr; FORWARD;
-
- { FILE UTILITIES }
- FUNCTION EqualFSSpecs(aFile, bFile: FSSpec): BOOLEAN; FORWARD;
- FUNCTION FileToTERec(fileSpec: FSSpec; teHndl: TEHandle): OSErr; FORWARD;
- FUNCTION FillHandlesFromFile(VAR listCount: INTEGER;
- listPtr: HandleListPtr; refNum: INTEGER; VAR xferCount: INTEGER): OSErr; FORWARD;
- FUNCTION GetFileAndSaveWndw(window: WindowPtr; useFS: BOOLEAN;
- VAR fileSpec: FSSpec): OSErr; FORWARD;
- FUNCTION MyCreateFSS(fileName: Str255; VAR fileSpec: FSSpec): OSErr; FORWARD;
- FUNCTION MyMakeFSSForWndw(window: WindowPtr; VAR theFSS: FSSpec): OSErr; FORWARD;
- FUNCTION TERecToFile(teHndl: TEHandle; fileSpec: FSSpec): OSErr; FORWARD;
- FUNCTION WriteHandlesToFile(listCount: INTEGER;
- listPtr: HandleListPtr; refNum: INTEGER; VAR xferCount: INTEGER): OSErr; FORWARD;
-
- { TEXT INFO & HANDLING }
- FUNCTION CompareTextDescs(text1: AEDesc; text2: AEDesc;
- VAR result: DescType): OSErr; FORWARD;
- FUNCTION CountDelChars(textPtr: Ptr; textLength: LongInt;
- delChar: SignedByte): LongInt; FORWARD;
- FUNCTION CountTextElems(srcText: TextToken; elemClass: DescType;
- VAR elemCount: LongInt): OSErr; FORWARD;
- FUNCTION CountWords(textPtr: Ptr; textLength: LongInt): LongInt; FORWARD;
- PROCEDURE DeleteThisText(myText: TextToken); FORWARD;
- FUNCTION DecodeInsertionLoc(insertionLoc: AEDesc; VAR relObjToken: AEDesc;
- VAR position: DescType): OSErr; FORWARD;
- PROCEDURE ExtendTextElem(VAR myText: TextToken); FORWARD;
- PROCEDURE ExtendWord(VAR myText: TextToken); FORWARD;
- FUNCTION GetDataFromTextProp(textPropDesc: AEDesc;
- VAR propDataDesc: AEDesc): OSErr; FORWARD;
- FUNCTION GetStyleItemFromConst(myConst: DescType; VAR stylItem: StyleItem;
- VAR plainFlag: BOOLEAN): BOOLEAN; FORWARD;
- FUNCTION GetTextElemFromText(srcText: TextToken; elemClass: DescType;
- elemIndex: LongInt; VAR elemText: TextToken): OSErr; FORWARD;
- FUNCTION GetTextFromDesc(srcDesc: AEDesc; VAR dstDesc: AEDesc): OSErr; FORWARD;
- PROCEDURE InitTextToken(VAR myText: TextToken); FORWARD;
- PROCEDURE InitTheStyles; FORWARD;
- FUNCTION IntlTextToText(intlTextDesc: AEDesc; VAR textDesc: AEDesc;
- VAR scrptCode: ScriptCode; VAR lngCode: LangCode): OSErr; FORWARD;
- FUNCTION ListToStyleSet(stylList: AEDesc; VAR styleSet: Style;
- VAR plainFlag: BOOLEAN; checkStyles: BOOLEAN): OSErr; FORWARD;
- FUNCTION MakeElemList(elemClass: DescType; srcText: TextToken;
- VAR elemList: AEDesc): OSErr; FORWARD;
- PROCEDURE MakeTextTokenForWndw(window: WindowPtr; VAR wndwText: TextToken); FORWARD;
- FUNCTION MyDoCut(window: WindowPtr): OSErr; FORWARD;
- FUNCTION MyDoCopy(window: WindowPtr): OSErr; FORWARD;
- FUNCTION MyDoPaste(window: WindowPtr): OSErr; FORWARD;
- FUNCTION MyGetTextElem(textPtr: Ptr; textLength: LongInt; delChar: SignedByte;
- elemIndex: LongInt; VAR elemOffset: LongInt; VAR elemLength: LongInt): OSErr; FORWARD;
- FUNCTION MyGetWord(textPtr: Ptr; textLength: LongInt; wordIndex: LongInt;
- VAR wordOffset: LongInt; VAR wordLength: LongInt): OSErr; FORWARD;
- FUNCTION MyGetUniformStyles(theTE: TEHandle; VAR onStyles: Style;
- VAR offStyles: Style): OSErr; FORWARD;
- PROCEDURE ScanToBreak(startPtr: Ptr; endPtr: Ptr; VAR breakPtr: Ptr); FORWARD;
- PROCEDURE ScanToDelimiter(startPtr: Ptr; endPtr: Ptr; delChar: SignedByte;
- VAR delPtr: Ptr); FORWARD;
- PROCEDURE ScanToNonBreak(startPtr: Ptr; endPtr: Ptr; VAR nbPtr: Ptr); FORWARD;
- FUNCTION SetDataForTextProp(textPropDesc: AEDesc; propDataDesc: AEDesc): OSErr; FORWARD;
- PROCEDURE SelectTextToken(theTextToken: TextToken); FORWARD;
- PROCEDURE SetFontForSelText(window: WindowPtr; fontName: Str255); FORWARD;
- PROCEDURE SetSizeForSelText(window: WindowPtr; newSize: INTEGER); FORWARD;
- FUNCTION SetStyleForSelText(window: WindowPtr; onStyles: Style;
- offStyles: Style): OSErr; FORWARD;
- FUNCTION SmartMakeStyleData(onStyles: Style; offStyles: Style;
- VAR styleData: AEDesc): OSErr; FORWARD;
- FUNCTION StyleDescToStyleSets(styleDesc: AEDesc; VAR onStyles: Style;
- VAR offStyles: Style; checkStyles: BOOLEAN): OSErr; FORWARD;
- FUNCTION StyleSetsToStyleDesc(onStyles: Style; offStyles: Style;
- VAR styleDesc: AEDesc; checkStyles: BOOLEAN; usePlain: BOOLEAN): OSErr; FORWARD;
- FUNCTION StyleSetToList(styleSet: Style; VAR stylList: AEDesc): OSErr; FORWARD;
- FUNCTION TextTokenToDesc(srcText: TextToken; VAR dstDesc: AEDesc): OSErr; FORWARD;
- FUNCTION TextToIntlText(textDesc: AEDesc; scrptCode: ScriptCode;
- lngCode: LangCode; VAR intlTextDesc: AEDesc): OSErr; FORWARD;
-
-
- { KEY BUFFERING }
- PROCEDURE CheckKeyBuffer; FORWARD;
- PROCEDURE ContinueKeyBuffering(key: CHAR; window: WindowPtr); FORWARD;
- PROCEDURE DestroyKeyBuffer; FORWARD;
- FUNCTION GrowKeyBuffer: BOOLEAN; FORWARD;
- PROCEDURE InitKeyBuffer; FORWARD;
- PROCEDURE InitKeyBufVals; FORWARD;
- PROCEDURE MyAEDoKey(key: CHAR; window: WindowPtr); FORWARD;
- PROCEDURE ResetKeyBuffer; FORWARD;
- PROCEDURE StartKeyBuffering(key: CHAR; window: WindowPtr); FORWARD;
-
- { TOKEN/LIST ROUTINES }
- FUNCTION CloseToken(theToken: AEDesc; saveOpt: DescType; gotDestFile: BOOLEAN;
- destFile: FSSpec): OSErr; FORWARD;
- FUNCTION CloseTokenList(theList: AEDesc; saveOpt: DescType; gotDestFile: BOOLEAN;
- destFile: FSSpec): OSErr; FORWARD;
- FUNCTION MoveToken(theToken: AEDesc; relObjToken: AEDesc;
- position: DescType): OSErr; FORWARD;
- FUNCTION MoveTokenList(theList: AEDesc; relObjToken: AEDesc;
- position: DescType): OSErr; FORWARD;
- FUNCTION PrintToken(theToken: AEDesc): OSErr; FORWARD;
- FUNCTION PrintTokenList(theList: AEDesc): OSErr; FORWARD;
-
- { MISC UTILITIES }
- FUNCTION BoolToStr(theBool: BOOLEAN): Str15; FORWARD;
- FUNCTION MyNumToStr(theNum: LONGINT): Str255; FORWARD;
- FUNCTION MyRandom(count: LongInt): LongInt; FORWARD;
-
- { ERROR HANDLING }
- FUNCTION CatchErr(theErr: OSErr; placeNum: INTEGER; VAR holdErr: OSErr): BOOLEAN; FORWARD;
- FUNCTION CheckErr(theErr: OSErr; placeNum: INTEGER): BOOLEAN; FORWARD;
- PROCEDURE DoItemErr(itemNum: INTEGER; theErr: OSErr; placeNum: INTEGER); FORWARD;
- PROCEDURE DoMyAlert(alertStr: Str255); FORWARD;
- PROCEDURE DoMyErr(theErr: OSErr; placeNum: INTEGER); FORWARD;
- FUNCTION QuietCatchErr(theErr: OSErr; VAR holdErr: OSErr): BOOLEAN; FORWARD;
-
- { AND . . . . }
- PROCEDURE DoHighLevelEvent(event: EventRecord); FORWARD;
-
- FUNCTION TypeToStr(thisType: DescType): Str15; FORWARD;
- PROCEDURE ShowObj(theObjSpec: AEDesc); FORWARD;
- PROCEDURE ShowEventAttrs(theAppleEvent: AppleEvent); FORWARD;
- FUNCTION HandleWild(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr; FORWARD;
- FUNCTION QuietGetSingularData(srcDesc: AEDesc; reqType: DescType;
- VAR dataDesc: AEDesc): OSErr; FORWARD;
-
-
- { END OF FORWARDS }
-
-
- { ROUTINES }
-
- {$S Initialize}
- FUNCTION TrapAvailable(tNumber: INTEGER; tType: TrapType): BOOLEAN;
-
- {Check to see if a given trap is implemented. This is only used by the
- Initialize routine in this program, so we put it in the Initialize segment.
- The recommended approach to see if a trap is implemented is to see if
- the address of the trap routine is the same as the address of the
- Unimplemented trap.}
- {Needs to be called after call to SysEnvirons so that it can check
- if a ToolTrap is out of range of a pre-MacII ROM.}
-
- BEGIN
- IF (tType = ToolTrap) &
- (gMac.machineType > envMachUnknown) &
- (gMac.machineType < envMacII) THEN BEGIN {it's a 512KE, Plus, or SE}
- tNumber := BAND(tNumber, $03FF);
- IF tNumber > $01FF THEN {which means the tool traps}
- tNumber := _Unimplemented; {only go to $01FF}
- END;
- TrapAvailable := NGetTrapAddress(tNumber, tType) <>
- GetTrapAddress(_Unimplemented);
- END; {TrapAvailable}
-
-
- {$S Main}
- FUNCTION IsDAWindow( window : WindowPtr ) : BOOLEAN;
-
- { Check if a window belongs to a desk accessory. }
-
- BEGIN { IsDAWindow }
- IF window = NIL THEN
- IsDAWindow := FALSE
- ELSE { DA windows have negative windowKinds }
- IsDAWindow := WindowPeek( window )^.windowKind < 0;
- END; { IsDAWindow }
-
-
-
- {$S Main}
- FUNCTION IsAppWindow( window : WindowPtr ) : BOOLEAN;
-
- { Check if a window belongs to the application. }
-
- BEGIN { IsAppWindow }
- IF window = NIL THEN
- IsAppWindow := FALSE
- ELSE { application windows have non-negative windowKinds }
- IsAppWindow := WindowPeek( window )^.windowKind >= 0;
- END; { IsAppWindow }
-
-
-
- {$S Main}
- PROCEDURE AlertUser( error : INTEGER );
-
- { Display an alert that tells the user an error occurred, then exit the program }
-
- VAR
- itemHit : INTEGER;
- message : Str255;
-
- BEGIN { AlertUser }
- SetCursor( arrow );
- GetIndString( message, kErrStrings, error );
- ParamText(message, '', '', '');
- itemHit := Alert( rUserError, NIL );
- END; { AlertUser }
-
-
- {$S Main}
- PROCEDURE GetTERect( window : WindowPtr; VAR teRect : Rect);
-
- { return a rectangle that is inset from the portRect by the size of
- the scrollbars and a little extra margin. }
-
- BEGIN { GetTERect }
- teRect := window^.portRect;
- InsetRect( teRect, kTextMargin, kTextMargin ); { adjust for margin }
- teRect.bottom := teRect.bottom - kScrollbarAdjust; { and for the scrollbars }
- teRect.right := teRect.right - kScrollbarAdjust;
- END; { GetTERect }
-
-
-
- {$S Main}
- PROCEDURE AdjustTE( window : WindowPtr );
-
- { Scroll the TERec around to match up to the potentially updated scrollbar
- values. This is really useful when the window resizes such that the
- scrollbars become inactive and the TERec had been previously scrolled. }
-
- VAR
- value : INTEGER;
-
- BEGIN { AdjustTE }
- WITH DocumentPeek( window )^ DO BEGIN
- TEScroll( ( docTE^^.viewRect.left - docTE^^.destRect.left ) - GetCtlValue( docHScroll ),
- ( docTE^^.viewRect.top - docTE^^.destRect.top ) -
- GetCtlValue( docVScroll ) , docTE );
- END; { with }
- END; { AdjustTE }
-
-
-
- {$S Main}
- PROCEDURE AdjustHV( isVert : BOOLEAN; control : ControlHandle;
- docTE : TEHandle; canRedraw : BOOLEAN );
-
- {Calculate the new control maximum value and current value, whether it is the horizontal or
- vertical scrollbar. The vertical max is calculated by comparing the number of lines to the
- vertical size of the viewRect. The horizontal max is calculated by comparing the maximum document
- width to the width of the viewRect. The current values are set by comparing the offset between
- the view and destination rects. If necessary and we canRedraw, have the control be re-drawn by
- calling ShowControl.}
-
- {TEStyleSample-vertical max originally used line by line calculations-lineheight was a
- constant value so it was easy to figure out what the range should be and pin the value
- within range. Now we need to use max and min values in pixels rather than in nlines}
-
- VAR
- value, max : INTEGER;
- oldValue, oldMax : INTEGER;
-
- BEGIN { AdjustHV }
- oldValue := GetCtlValue( control );
- oldMax := GetCtlMax( control );
- IF isVert THEN BEGIN
- { new for TEStyleSample }
- max := ( TEGetHeight( docTE^^.nLines, 0, docTE ) ) -
- ( docTE^^.viewRect.bottom - docTE^^.viewRect.top );
-
- END ELSE
- max := kMaxDocWidth - (docTE^^.viewRect.right - docTE^^.viewRect.left );
-
- IF max < 0 THEN
- max := 0; { check for negative values }
- SetCtlMax( control, max );
- IF isVert THEN
- value := docTE^^.viewRect.top - docTE^^.destRect.top
- ELSE
- value := docTE^^.viewRect.left - docTE^^.destRect.left;
- IF value < 0 THEN
- value := 0
- ELSE IF value > max THEN
- value := max; { pin the value to within range }
- SetCtlValue( control, value );
- IF canRedraw & ( ( max <> oldMax ) | ( value <> oldValue ) ) THEN
- ShowControl( control ); { check to see if the control can be re-drawn }
- END; { AdjustHV }
-
-
-
- {$S Main}
- PROCEDURE AdjustScrollValues( window : WindowPtr; canRedraw : BOOLEAN );
-
- { Simply call the common adjust routine for the vertical and horizontal scrollbars. }
-
- BEGIN { AdjustScrollValues }
- WITH DocumentPeek( window )^ DO BEGIN
- AdjustHV( TRUE, docVScroll, docTE, canRedraw );
- AdjustHV( FALSE, docHScroll, docTE, canRedraw );
- END; { with }
- END; { AdjustScrollValues }
-
-
-
- {$S Main}
- PROCEDURE AdjustScrollSizes( window : WindowPtr );
-
- { Re-calculate the position and size of the viewRect and the scrollbars.
- kScrollTweek compensates for off-by-one requirements of the scrollbars
- to have borders coincide with the growbox. }
-
- VAR
- teRect : Rect;
-
- BEGIN { AdjustScrollSizes }
- GetTERect( window, teRect ); {start with teRect}
- WITH DocumentPeek( window )^, window^.portRect DO BEGIN
- docTE^^.viewRect := teRect;
-
- { AdjustViewRect(docTE) was removed--no longer needed }
-
- MoveControl( docVScroll, right - kScrollbarAdjust, -1 );
- SizeControl( docVScroll, kScrollbarWidth, ( bottom - top ) -
- ( kScrollbarAdjust - kScrollTweek ) );
- MoveControl( docHScroll, -1, bottom - kScrollbarAdjust );
- SizeControl( docHScroll, ( right - left ) - ( kScrollbarAdjust -
- kScrollTweek ), kScrollbarWidth );
- END; { with }
- END; { AdjustScrollSizes }
-
-
-
- {$S Main}
- PROCEDURE AdjustScrollbars( window : WindowPtr; needsResize : BOOLEAN );
-
- { Turn off the controls by jamming a zero into their contrlVis fields
- (HideControl erases them and we don't want that). If the controls are to
- be resized as well, call the procedure to do that, then call the procedure
- to adjust the maximum and current values. Finally re-enable the controls
- by jamming a $FF in their contrlVis fields. }
-
- VAR
- oldMax, oldVal : INTEGER;
-
- BEGIN { AdjustScrollbars }
- WITH DocumentPeek( window )^ DO BEGIN
- docVScroll^^.contrlVis := kControlInvisible; { turn them off }
- docHScroll^^.contrlVis := kControlInvisible;
- IF needsResize THEN { move and size if needed }
- AdjustScrollSizes( window );
- AdjustScrollValues( window, NOT needsResize ); { fool with max and current value }
- { Now, restore visibility in case we never had to ShowControl during adjustment }
- docVScroll^^.contrlVis := kControlVisible; { turn them on }
- docHScroll^^.contrlVis := kControlVisible;
- END;
- END; { AdjustScrollbars }
-
-
-
- {$S Main}
- {$PUSH} {$Z+}
- PROCEDURE PascalClikLoop;
-
- { Gets called from our assembly language routine, AsmClikLoop, which is in
- turn called by the TEClick toolbox routine. Saves the windows clip region,
- sets it to the portRect, adjusts the scrollbar values to match the TE scroll
- amount, then restores the clip region. }
-
- VAR
- window : WindowPtr;
- region : RgnHandle;
-
- BEGIN { PascalClikLoop }
- window := FrontWindow;
- region := NewRgn;
- GetClip( region ); { save the old clip }
- ClipRect( window^.portRect ); { set the new clip }
- AdjustScrollValues( window, TRUE ); { pass TRUE for canRedraw }
- SetClip( region ); { restore the old clip }
- DisposeRgn( region );
- END; { PascalClikLoop }
- {$POP}
-
-
-
- {$S Main}
- {$PUSH} {$Z+}
- FUNCTION GetOldClikLoop : ProcPtr;
-
- { Gets called from our assembly language routine, AsmClikLoop, which is in
- turn called by the TEClick toolbox routine. It returns the address of the
- default clikLoop routine that was put into the TERec by TEAutoView to
- AsmClikLoop so that it can call it. }
-
- BEGIN { GetOldClikLoop }
- GetOldClikLoop := DocumentPeek( FrontWindow )^.docClik;
- END; { GetOldClikLoop }
- {$POP}
-
-
-
- PROCEDURE AsmClikLoop; EXTERNAL;
-
- { A reference to our assembly language routine that gets attached to the clikLoop
- field of our TE record. }
-
-
- {$S Main}
- PROCEDURE BigBadError( error : INTEGER );
- BEGIN
- AlertUser( error );
- ExitToShell;
- END;
-
-
-
- {$S Initialize}
- PROCEDURE Initialize;
-
- { Set up the whole world, including global variables, Toolbox managers,
- menus, and a single blank document.}
-
- {If an error is detected, instead of merely doing an ExitToShell,
- which leaves the user without much to go on, we call AlertUser, which puts
- up a simple alert that just says an error occurred and then calls ExitToShell.
- Since there is no other cleanup needed at this point if an error is detected,
- this form of error- handling is acceptable. If more sophisticated error recovery
- is needed, an exception mechanism, such as is provided by Signals, can be used.}
- { CHANGES FOR QUILL:
- (1) moved up gHasWaitNextEvent
- (2) put in InitAEHandlers
- (3) commented out the grab-3-events stuff - **CHECK
- (4) put in gDocCount
- (5) took out the DoNew (the OpenApp event takes care of it)
- (6) init gNullDesc and gSelfAddrDesc
- }
-
- VAR
- menuBar : Handle;
- total, contig : LongInt;
- event : EventRecord;
- count : INTEGER;
-
- PROCEDURE BigBadError( error : INTEGER );
- BEGIN
- AlertUser( error );
- ExitToShell;
- END;
-
- BEGIN { Initialize }
- gHasWaitNextEvent := TrapAvailable(_WaitNextEvent, ToolTrap); { **CHECK on this }
- gInBackground := FALSE;
-
- gErrorDesc := gNullDesc;
-
- InitGraf(@thePort);
- InitFonts;
- InitWindows;
- InitMenus;
- TEInit;
- InitDialogs(NIL);
- InitCursor;
- InitAEHandlers;
- InitTheStyles;
-
- gInHandler := FALSE;
- gShowAllErrs := FALSE;
-
-
- FOR count := 1 TO 3 DO
- gTempBool := EventAvail(everyEvent, event); { **CHECK on this, too }
- gTempLong := SysEnvirons(kSysEnvironsVersion, gMac);
- IF gMac.machineType < 0 THEN BigBadError(eWrongMachine);
-
-
- IF ORD( GetApplLimit ) - ORD( ApplicZone ) < kMinHeap THEN
- BigBadError( eSmallSize );
- PurgeSpace( total, contig );
- IF total < kMinSpace THEN
- IF UnloadScrap <> noErr THEN
- BigBadError( eNoMemory )
- ELSE BEGIN
- PurgeSpace( total, contig );
- IF total < kMinSpace THEN
- BigBadError( eNoMemory );
- END; { if }
-
- menuBar := GetNewMBar( rMenuBar ); { read menus into menu bar }
- IF menuBar = NIL THEN
- BigBadError( eNoMemory );
- SetMenuBar( menuBar ); { install menus }
- DisposHandle( menuBar );
- AddResMenu( GetMHandle( mApple ), 'DRVR' ); { add DA names to Apple menu }
- AddResMenu( GetMHandle( mFont ),'FONT' ); { add Font names to Font Menu }
- DrawMenuBar;
- gNumDocuments := 0;
- gDocCount := 0;
- { do other initialization here }
- { set up printer stuff-this will allow the default pageSetup parameters to be used, so if
- the used decides to print with out using pageSetup everything will be okay }
-
- { create a "null descriptor" to serve as a default container }
- gNullDesc.descriptorType := typeNull;
- gNullDesc.dataHandle := NIL;
-
- { create a address descriptor for sending things to myself }
- IF CheckErr( MakeSelfAddr(gSelfAddrDesc) , 3714 ) THEN BigBadError(eNoSelfAddr);
-
- gPrinterRecord := THPrint( NewHandle( SizeOF( TPrint ) ) ); {allocate a print record}
- IF gPrinterRecord <> NIL THEN BEGIN {if we're successful then setup the default settings}
- PrOpen; {open the record }
- PrintDefault( gPrinterRecord ); { load in default settings }
- PrClose; { close it up }
- END; { if }
-
- InitKeyBuffer;
-
- END; {Initialize}
-
- {$S Main}
- PROCEDURE AdjustMenus;
- { CHANGES FOR QUILL: new menu items, multiple windows }
-
- VAR
- window : WindowPtr;
- menu : MenuHandle;
- offset : LONGINT;
- undo : BOOLEAN; { flag to enable/disable undo command }
- cutCopyClear : BOOLEAN; { flag to enable/disable editing commands }
- paste : BOOLEAN;
- selectAll : BOOLEAN;
-
- doPrint : BOOLEAN; { flag to enable/disable printing item }
-
- te : TEHandle; { local te handle }
- mode : INTEGER; { current style }
-
-
- BEGIN
- window := FrontWindow;
-
- menu := GetMHandle( mFile );
- EnableItem(menu,iQuit); { always enabled }
- EnableItem(menu,iQuitNow); { always enabled }
- EnableItem(menu,iPrintFile); { always enabled }
-
- IF gNumDocuments < kMaxOpenDocuments THEN
- BEGIN
- EnableItem( menu, iNew ); { New, Open enabled when we can open more documents }
- EnableItem(menu,iOpen);
- END
- ELSE
- BEGIN
- DisableItem( menu, iNew );
- DisableItem(menu,iOpen);
- END;
-
- IF window <> NIL THEN { Close, Save, SaveAs enabled when there is an active window } { well, Save is a special case }
- BEGIN
- EnableItem( menu, iClose );
- IF WindowIsDirty(window) THEN EnableItem( menu , iSave ) ELSE DisableItem(menu,iSave);
- EnableItem( menu, iSaveAs);
- END
- ELSE
- BEGIN
- DisableItem( menu, iClose );
- DisableItem( menu , iSave );
- DisableItem( menu, iSaveAs );
- END;
-
- menu := GetMHandle( mEdit );
- undo := FALSE;
- cutCopyClear := FALSE;
- paste := FALSE;
- selectAll := FALSE;
- doPrint := FALSE;
-
- IF IsDAWindow( window ) THEN BEGIN
- undo := TRUE; { all editing is enabled for DA windows }
- cutCopyClear := TRUE;
- paste := TRUE;
- selectAll := TRUE;
- END ELSE IF IsAppWindow( window ) THEN BEGIN
- WITH DocumentPeek( window )^.docTE^^ DO
- IF selStart < selEnd THEN BEGIN
- cutCopyClear := TRUE;
- END; { if }
- { Cut, Copy, and Clear is enabled for app. windows with selections }
- IF GetScrap( NIL, 'TEXT', offset ) > 0 THEN
- paste := TRUE; { Paste is enabled for app. windows }
-
- selectAll := TRUE;
- doPrint := TRUE;
-
- mode := doFace;
- menu := GetMHandle( mStyle );
- IF TEContinuousStyle( mode, gTxStyle, DocumentPeek( window )^.docTE ) THEN BEGIN
- CheckItem( menu, iPlain, gTxStyle.tsface = [] );
- CheckItem( menu, iBold, bold in gTxStyle.tsFace );
- CheckItem( menu, iItalic, italic in gTxStyle.tsFace );
- CheckItem( menu, iUnderline, underline in gTxStyle.tsFace );
- CheckItem( menu, iOutline, outline in gTxStyle.tsFace );
- CheckItem( menu, iShadow, shadow in gTxStyle.tsFace );
- END ELSE BEGIN
- CheckItem( menu, iPlain, FALSE );
- CheckItem( menu, iBold, FALSE );
- CheckItem( menu, iItalic, FALSE );
- CheckItem( menu, iUnderline, FALSE );
- CheckItem( menu, iOutline, FALSE );
- CheckItem( menu, iShadow, FALSE );
- END; { if }
-
- END; { if }
- menu := GetMHandle( mEdit );
-
- IF undo THEN
- EnableItem( menu, iUndo )
- ELSE
- DisableItem( menu, iUndo );
-
- IF cutCopyClear THEN BEGIN
- EnableItem( menu, iCut );
- EnableItem( menu, iCopy );
- EnableItem( menu, iClear );
- END ELSE BEGIN
- DisableItem( menu, iCut );
- DisableItem( menu, iCopy );
- DisableItem( menu, iClear );
- END; { if }
-
-
- IF paste THEN
- EnableItem( menu, iPaste )
- ELSE
- DisableItem( menu, iPaste );
-
- IF selectAll THEN
- EnableItem( menu, iSelectAll )
- ELSE
- DisableItem( menu, iSelectAll );
-
-
- menu := GetMHandle( mFile );
- IF doPrint THEN BEGIN
- EnableItem( menu, iPageSetup );
- EnableItem( menu, iPrint );
- END ELSE BEGIN
- DisableItem( menu, iPageSetup );
- DisableItem( menu, iPrint );
- END; { if }
-
- menu := GetMHandle(mMathoms);
- EnableItem(menu,iShowAllErrs);
- CheckItem(menu,iShowAllErrs,gShowAllErrs);
-
- END; { AdjustMenus }
-
- {$S Main}
- PROCEDURE DoMenuCommand( menuResult : LONGINT );
-
- { This is called when an item is chosen from the menu bar (after calling
- MenuSelect or MenuKey). It does the right thing for each command. }
- { CHANGES FOR QUILL: many cases now call new routines that make
- use of AppleEvents. Also added new cases. }
- VAR
- menuID, menuItem : INTEGER;
- itemHit, daRefNum : INTEGER;
- daName : Str255;
-
- tempStr : Str255;
- menu : MenuHandle;
-
- ignoreResult, saveErr : OSErr;
- handledByDA : BOOLEAN;
- te : TEHandle;
- window : WindowPtr;
- aHandle : Handle;
- oldSize, newSize : LONGINT;
- total, contig : LONGINT;
-
-
- BEGIN
- window := FrontWindow;
- menuID := HiWrd( menuResult ); { use built-ins (for efficiency)... }
- menuItem := LoWrd( menuResult ); { to get menu item number and menu number }
- te := DocumentPeek( window )^.docTE;
-
- CASE menuID OF
-
- mApple:
- CASE menuItem OF
- iAbout: {bring up alert for About}
- BEGIN
- { Debugger;}
- itemHit := Alert(rAboutAlert, NIL);
-
- END;
-
- OTHERWISE BEGIN { all non-About items in this menu are DAs }
- GetItem( GetMHandle( mApple ), menuItem, daName );
- daRefNum := OpenDeskAcc( daName );
- END; { otherwise }
- END; { case }
-
- mFile:
- CASE menuItem OF
- iNew: DoMenuNew;
- iOpen: DoMenuOpen;
- iClose: DoMenuClose(window);
- iSave: DoMenuSave(window);
- iSaveAs: DoMenuSaveAs(window);
-
- iPageSetup:
- BEGIN
- PrOpen;
- IF PrError = noErr THEN gTempBool := PrStlDialog( gPrinterRecord );
- PrClose;
- END; { iPageSetup }
-
- iPrint: DoMenuPrint;
- iPrintFile: DoMenuPrintFile;
- iQuit: DoMenuQuit;
- iQuitNow: DoMenuQuitNow;
- END; { case }
-
- mEdit: BEGIN { call SystemEdit for DA editing & MultiFinder }
- IF NOT SystemEdit( menuItem -1 ) THEN BEGIN
- CASE menuItem OF
-
- iCut, iCopy, iPaste: DoMenuEdit(window,menuItem);
-
- iClear:
- BEGIN
- TEDelete( te );
- DirtyWindow(window);
- END;
-
- iSelectAll:
- TESetSelect( 0, te^^.teLength, te );
-
- END; { case }
- if menuItem <> iCopy then
- AdjustScrollBars( window, FALSE );
- END; { if }
- END; { mEdit }
-
- mFont :
- BEGIN { mFont }
- GetItem( GetMHandle( mFont ), menuItem, gFontName );
- SetFontForSelText(window,gFontName);
- END; { mFont }
-
- mFontSize :
- BEGIN { mFontSize }
- CASE menuItem OF
- iNine : gFontSize := 9;
- iTen : gFontSize := 10;
- iTwelve : gFontSize := 12;
- iFourteen : gFontSize := 14;
- iEighteen : gFontSize := 18;
- iTwoFour : gFontSize := 24;
- END; { case }
-
- SetSizeForSelText(window,gFontSize);
- END; { mFontSize }
-
- mStyle : DoMenuStyle(window,menuItem);
-
- mMathoms: DoMenuMathoms(menuItem);
-
- END; { case }
- HiliteMenu( 0 ); { unhighlight what MenuSelect (or MenuKey) hilited }
- END; { DoMenuCommand }
-
-
-
- {$S Main}
- PROCEDURE DrawWindow( window : WindowPtr );
-
- { Draw the contents of an application window. }
-
- BEGIN { DrawWindow }
- SetPort( window );
- WITH window^ DO BEGIN
- EraseRect( portRect ); { as per TextEdit chapter of Inside Macintosh }
- DrawControls( window ); { this ordering makes for a better appearance }
- DrawGrowIcon( window );
- TEUpdate( portRect, DocumentPeek( window )^.docTE );
- END; { with }
- END; { DrawWindow }
-
-
-
- {$S Main}
- FUNCTION GetSleep : LONGINT;
-
- { Calculate a sleep value for WaitNextEvent. This takes into account the things
- that DoIdle does with idle time. }
-
- VAR
- sleep : LONGINT;
- window : WindowPtr;
-
- BEGIN { GetSleep }
- sleep := MAXLONGINT; { default value for sleep }
- IF NOT gInBackground THEN BEGIN { if we are in front... }
- window := FrontWindow; { and the front window is ours... }
- IF IsAppWindow( window ) THEN BEGIN
- WITH DocumentPeek( window )^.docTE^^ DO
- IF selStart = selEnd THEN { and the selection is an insertion point... }
- sleep := GetCaretTime; { we need to blink the insertion point }
- END; { if }
- END; { if }
- GetSleep := sleep;
- END; { GetSleep }
-
-
-
- {$S Main}
- PROCEDURE CommonAction( control : ControlHandle; VAR amount : INTEGER );
-
- { Common algorithm for setting the new value of a control. It returns the actual amount
- the value of the control changed. Note the pinning is done for the sake of returning
- the amount the control value changed. }
-
- VAR
- value, max : INTEGER;
- window : WindowPtr;
-
- BEGIN { CommonAction }
- value := GetCtlValue( control ); { get current value }
- max := GetCtlMax( control ); { and max value }
- amount := value - amount;
- IF amount < 0 THEN
- amount := 0
- ELSE IF amount > max THEN
- amount := max;
- SetCtlValue( control, amount );
- amount := value - amount; { calculate true change }
- END; { CommonAction }
-
-
-
- {$S Main}
- PROCEDURE VActionProc( control : ControlHandle; part : INTEGER );
-
- { Determines how much to change the value of the vertical scrollbar by and how
- much to scroll the TE record. }
-
- VAR
- amount : INTEGER;
- window : WindowPtr;
-
- BEGIN { VActionProc }
- IF part <> 0 THEN BEGIN
- window := control^^.contrlOwner;
- WITH DocumentPeek( window )^, DocumentPeek( window )^.docTE^^ DO BEGIN
- CASE part OF
- inUpButton, inDownButton :
- amount := 24;
- inPageUp, inPageDown :
- amount := viewRect.bottom - viewRect.top; { one page }
- END; { case }
- IF ( part = inDownButton ) | ( part = inPageDown ) THEN
- amount := -amount; { reverse direction }
- CommonAction( control, amount );
- IF amount <> 0 THEN
- TEScroll( 0, amount, docTE );
- END; { with }
- END; { if }
- END; { VActionProc }
-
-
-
- {$S Main}
- PROCEDURE HActionProc( control : ControlHandle; part : INTEGER );
-
- { Determines how much to change the value of the horizontal scrollbar by and how
- much to scroll the TE record. }
-
- VAR
- amount : INTEGER;
- window : WindowPtr;
-
- BEGIN { HActionProc }
- IF part <> 0 THEN BEGIN
- window := control^^.contrlOwner;
- WITH DocumentPeek( window )^, DocumentPeek( window )^.docTE^^ DO BEGIN
- CASE part OF
- inUpButton, inDownButton :
- amount := kButtonScroll; { a few pixels }
- inPageUp, inPageDown :
- amount := viewRect.right - viewRect.left; { a page }
- END; { case }
- IF ( part = inDownButton ) | ( part = inPageDown ) THEN
- amount := -amount; { reverse direction }
- CommonAction( control, amount );
- IF amount <> 0 THEN
- TEScroll( amount, 0, docTE );
- END; { with }
- END; { if }
- END; { HActionProc }
-
-
-
- {$S Main}
- PROCEDURE DoIdle;
-
- { This is called whenever we get an null event or a mouse-moved event.
- It takes care of necessary periodic actions. For this program, it calls TEIdle. }
-
- VAR
- window : WindowPtr;
-
- BEGIN { DoIdle }
- window := FrontWindow;
- IF IsAppWindow( window ) THEN
- TEIdle( DocumentPeek( window )^.docTE );
- END; { DoIdle }
-
-
-
- {$S Main}
- PROCEDURE DoKeyDown( event : EventRecord );
-
- { This is called for any keyDown or autoKey events, except when the
- Command key is held down. It looks at the frontmost window to decide what
- to do with the key typed. }
-
- VAR
- window : WindowPtr;
- key : CHAR;
- te : TEHandle;
-
- BEGIN
- window := FrontWindow;
- IF IsAppWindow( window ) THEN BEGIN
- te := DocumentPeek( window)^.docTE;
- key := CHR( BAnd( event.message, charCodeMask ) );
- IF ( key = CHR(kDelChar ) ) | { don't count deletes }
- ( te^^.teLength - ( te^^.selEnd - te^^.selStart )
- + 1 < kMaxTELength ) THEN BEGIN { but check haven't gone past }
-
- { we will treat arrow keys (which change the selection) like non-key events - }
- { that is, check the key buffer, and DON'T buffer the arrow key (we could do }
- { more complicated stuff, but is it worth it?) }
-
- IF (key = CHR(kRightArrow)) | (key = CHR(kLeftArrow)) | (key = CHR(kUpArrow)) | (key = CHR(kDownArrow))
- THEN CheckKeyBuffer
- ELSE MyAEDoKey(key,window); { must do this BEFORE TEKey or we won't record the selection range right }
-
- TEKey( key, te );
- DirtyWindow(window);
- AdjustScrollbars( window, FALSE );
- END ELSE
- { **CHECK - should we even try to dump the key buffer here? }
- AlertUser( eExceedChar );
- END; { if }
- END; { DoKeyDown }
-
-
-
- {$S Main}
- PROCEDURE DoContentClick( window : WindowPtr; event : EventRecord );
-
- { Called when a mouseDown occurs in the content of a window. }
-
- VAR
- mouse : Point;
- control : ControlHandle;
- part, value : INTEGER;
- shiftDown : BOOLEAN;
- teRect : Rect;
-
- BEGIN { DoContentClick }
- IF IsAppWindow( window ) THEN BEGIN
- SetPort( window );
- mouse := event.where; { get the click position }
- GlobalToLocal( mouse ); { convert to local coordinates }
-
- GetTERect( window, teRect );
- IF PtInRect( mouse, teRect ) THEN BEGIN
- shiftDown := BAnd( event.modifiers, shiftKey ) <> 0; { extend if Shift is down }
- TEClick( mouse, shiftDown, DocumentPeek( window )^.docTE );
- END ELSE BEGIN
- part := FindControl( mouse, window, control );
- WITH DocumentPeek( window )^ DO
- CASE part OF
- 0:; { do nothing for viewRect case }
- inThumb: BEGIN
- value := GetCtlValue( control );
- part := TrackControl( control, mouse, NIL );
- IF part <> 0 THEN BEGIN
- value := value - GetCtlValue( control );
- IF value <> 0 THEN
- IF control = docVScroll THEN
- TEScroll( 0, value, docTE )
- ELSE
- TEScroll( value, 0, docTE );
- END; { if }
- END; { inThumb }
- OTHERWISE { must be page or button }
- IF control = docVScroll THEN
- value := TrackControl( control, mouse, @VActionProc )
- ELSE
- value := TrackControl( control, mouse, @HActionProc );
- END; { case }
- END; { if }
- END; { if }
- END; { DoContentClick }
-
-
-
- {$S Main}
- PROCEDURE ResizeWindow( window : WindowPtr );
-
- { Called when the window has been resized to fix up the controls and content }
-
- BEGIN { ResizeWindow }
- WITH window^ DO BEGIN
- AdjustScrollbars( window, TRUE );
- AdjustTE( window );
- InvalRect( portRect );
- END;
- END; { ResizeWindow }
-
-
-
- {$S Main}
- PROCEDURE GetLocalUpdateRgn( window : WindowPtr; localRgn : RgnHandle );
-
- { Returns the update region in local coordinates }
-
- BEGIN { GetLocalUpdateRgn }
- CopyRgn( WindowPeek( window )^.updateRgn, localRgn ); { save old update region }
- WITH window^.portBits.bounds DO
- OffsetRgn( localRgn, left, top ); { convert to local coords }
- END; { GetLocalUpdateRgn }
-
-
-
- {$S Main}
- PROCEDURE DoGrowWindow( window : WindowPtr; event : EventRecord );
-
- { Called when a mouseDown occurs in the grow box of an active window. In
- order to eliminate any 'flicker', we want to invalidate only what is
- necessary. Since ResizeWindow invalidates the whole portRect, we save
- the old TE viewRect, intersect it with the new TE viewRect, and
- remove the result from the update region. However, we must make sure
- that any old update region that might have been around gets put back. }
- { CHANGES FOR QUILL: added an AppleEvent "set rectangle" call
- for recording purposes (we let the OS actually grow the window for us,
- then send an AppleEvent to set the rect of the window to its new value -
- a null operation, in effect, but it will record the rect change for us) }
-
- VAR growResult: LONGINT;
- tempRect: Rect;
- tempRgn: RgnHandle;
- ignoreResult: BOOLEAN;
- index: INTEGER;
-
- BEGIN { DoGrowWindow }
- WITH screenBits.bounds DO
- SetRect( tempRect, kMinDocDim, kMinDocDim, right, bottom ); { set up limiting values }
- growResult := GrowWindow( window, event.where, tempRect );
- IF growResult <> 0 THEN { see if changed size }
- WITH DocumentPeek( window )^, window^ DO BEGIN
- tempRect := docTE^^.viewRect; { save old text box }
- tempRgn := NewRgn;
- GetLocalUpdateRgn( window, tempRgn ); { get localized update region }
- SizeWindow( window, LoWrd( growResult ), HiWrd( growResult ), TRUE );
- ResizeWindow( window );
- ignoreResult := SectRect( tempRect, docTE^^.viewRect, tempRect ); { find what stayed same }
- ValidRect( tempRect ); { take it out of update }
- InvalRgn( tempRgn ); { put back any prior update }
- DisposeRgn( tempRgn );
- END; { with }
- { now, for recording purposes, send an AppleEvent to myself
- (re)setting the window to its current rectangle }
- tempRect := WindowPeek(window)^.strucRgn^^.rgnBBox; { we use the structure rect for that }
- index := IndexFromWndwPtr(window);
- SendAESetWndwRect(index,tempRect);
- END; { DoGrowWindow }
-
-
-
- {$S Main}
- PROCEDURE DoZoomWindow( window : WindowPtr; part : INTEGER );
-
- { Called when a mouseClick occurs in the zoom box of an active window.
- Everything has to get re-drawn here, so we don't mind that
- ResizeWindow invalidates the whole portRect. }
-
- BEGIN { DoZoomWindow }
- WITH window^ DO BEGIN
- EraseRect( portRect );
- ZoomWindow( window, part, ( window = FrontWindow ) );
- ResizeWindow( window );
- END; { with }
- END; { DoZoomWindow }
-
-
-
- {$S Main}
- PROCEDURE DoUpdate( window : WindowPtr );
-
- { This is called when an update event is received for a window.
- It calls DrawWindow to draw the contents of an application window,
- but only if the visRgn is non-empty; for efficiency reasons,
- not because it is required. }
-
- BEGIN { DoUpdate }
- IF IsAppWindow( window ) THEN BEGIN
- BeginUpdate( window ); { this sets up the visRgn }
- IF NOT EmptyRgn( window^.visRgn ) THEN { draw if updating needs to be done }
- DrawWindow( window );
- EndUpdate( window );
- END; { if }
- END; { DoUpdate }
-
-
-
- {$S Main}
- PROCEDURE DoActivate( window : WindowPtr; becomingActive : BOOLEAN );
-
- { This is called when a window is activated or deactivated. }
-
- VAR
- tempRgn, clipRgn : RgnHandle;
- growRect : Rect;
-
- BEGIN { DoActivate }
- IF IsAppWindow( window ) THEN
- WITH DocumentPeek( window )^ DO
- IF becomingActive THEN BEGIN
- { since we don’t want TEActivate to draw a selection in an area where
- we’re going to erase and redraw, we’ll clip out the update region
- before calling it. }
- tempRgn := NewRgn;
- clipRgn := NewRgn;
- GetLocalUpdateRgn( window, tempRgn ); { get localized update region }
- GetClip( clipRgn );
- DiffRgn( clipRgn, tempRgn, tempRgn ); { subtract updateRgn from clipRgn }
- SetClip( tempRgn );
- TEActivate( docTE ); { let TE do its thing }
- SetClip( clipRgn ); { restore the full-blown clipRgn }
- DisposeRgn( tempRgn );
- DisposeRgn( clipRgn );
-
- {the controls need to be redrawn on activation:}
- docVScroll^^.contrlVis := kControlVisible;
- docHScroll^^.contrlVis := kControlVisible;
- InvalRect( docVScroll^^.contrlRect );
- InvalRect( docHScroll^^.contrlRect );
- { the growbox needs to be redrawn on activation: }
- growRect := window^.portRect;
- WITH growRect DO BEGIN
- top := bottom - kScrollbarAdjust; { adjust for the scrollbars }
- left := right - kScrollbarAdjust;
- END; { with }
- InvalRect( growRect );
- END ELSE BEGIN
- TEDeactivate( docTE );
- { the controls should be hidden immediately on deactivation: }
- HideControl( docVScroll );
- HideControl( docHScroll );
- { the growbox should be changed immediately on deactivation: }
- DrawGrowIcon( window );
- END; { if }
- END; { DoActivate }
-
-
-
- {$S Main}
- PROCEDURE GetGlobalMouse(VAR mouse: Point);
-
- {Get the global coordinates of the mouse. When you call OSEventAvail
- it will return either a pending event or a null event. In either case,
- the where field of the event record will contain the current position
- of the mouse in global coordinates and the modifiers field will reflect
- the current state of the modifiers. Another way to get the global
- coordinates is to call GetMouse and LocalToGlobal, but that requires
- being sure that thePort is set to a valid port.}
-
- VAR
- event : EventRecord;
-
- BEGIN
- IF OSEventAvail(kNoEvents, event) THEN; {we aren't interested in any events}
- mouse := event.where; {just the mouse position}
- END;
-
-
-
- {$S Main}
- PROCEDURE AdjustCursor( mouse : Point; region : RgnHandle );
-
- { Change the cursor's shape, depending on its position. This also calculates a region
- that includes the cursor for WaitNextEvent. }
-
- VAR
- window : WindowPtr;
- arrowRgn : RgnHandle;
- iBeamRgn : RgnHandle;
- iBeamRect : Rect;
-
- BEGIN { AdjustCursor }
- window := FrontWindow; { we only adjust the cursor when we are in front }
- IF ( NOT gInBackground ) AND ( NOT IsDAWindow( window ) ) THEN BEGIN
- { calculate regions for different cursor shapes}
- arrowRgn := NewRgn;
- iBeamRgn := NewRgn;
-
- { start with a big, big rectangular region }
- SetRectRgn( arrowRgn, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos );
-
- { calculate iBeamRgn }
- IF IsAppWindow( window ) THEN BEGIN
- iBeamRect := DocumentPeek( window )^.docTE^^.viewRect;
- SetPort( window ); { make a global version of the viewRect }
- WITH iBeamRect DO BEGIN
- LocalToGlobal( topLeft );
- LocalToGlobal( botRight );
- END; { with }
- RectRgn( iBeamRgn, iBeamRect );
- WITH window^.portBits.bounds DO
- SetOrigin( -left, -top );
- SectRgn( iBeamRgn, window^.visRgn, iBeamRgn );
- SetOrigin( 0, 0 );
- END; { if }
-
- { subtract other regions from arrowRgn }
- DiffRgn( arrowRgn, iBeamRgn, arrowRgn );
-
- {change the cursor and the region parameter}
- IF PtInRgn( mouse, iBeamRgn ) THEN BEGIN
- SetCursor( GetCursor( iBeamCursor )^^ );
- CopyRgn( iBeamRgn, region );
- END ELSE BEGIN
- SetCursor( arrow );
- CopyRgn( arrowRgn, region );
- END; { if }
-
- { get rid of our local regions }
- DisposeRgn( arrowRgn );
- DisposeRgn( iBeamRgn );
- END; { if }
- END; { AdjustCursor }
-
-
-
- {$S Main}
- PROCEDURE DoEvent( event : EventRecord );
-
- { Do the right thing for an event. Determine what kind of event it is, and call
- the appropriate routines. }
- { CHANGES FOR QUILL: call new routines DoDragWindow, DoMenuClose;
- added kHighLevelEvent case }
-
- VAR
- part, err : INTEGER;
- window : WindowPtr;
- key : CHAR;
- ignore : BOOLEAN;
- aPoint : Point;
-
- BEGIN { DoEvent }
- CASE event.what OF
- nullEvent:
- DoIdle;
- mouseDown: BEGIN
-
- CheckKeyBuffer;
-
- part := FindWindow( event.where, window );
- CASE part OF
-
- inMenuBar : BEGIN
- AdjustMenus;
- DoMenuCommand( MenuSelect( event.where ) );
- END; { inMenuBar }
-
- inSysWindow :
- SystemClick( event, window );
-
- inContent :
- IF window <> FrontWindow THEN BEGIN
- { wndwIndex := IndexFromWndwPtr(window);
- IF wndwIndex <> 0 THEN SendAEMove(wndwIndex,1,kAEBefore);}
- MyBringWndwFront(window);
- {SelectWindow(window);}
- {DoEvent(event);} {use this line for "do first click"}
- END ELSE
- DoContentClick( window, event );
-
- inDrag :
- DoDragWindow( window, event.where, screenBits.bounds );
-
- inGrow:
- DoGrowWindow( window, event );
-
- inGoAway:
- IF TrackGoAway( window, event.where ) THEN DoMenuClose( window );
-
- inZoomIn, inZoomOut:
-
- IF TrackBox(window, event.where, part) THEN
- DoZoomWindow( window, part );
- END; { case }
- END; { mouseDown }
-
- keyDown, autoKey : BEGIN
- key := CHR( BAnd( event.message, charCodeMask ) );
- IF BAnd( event.modifiers, cmdKey ) <> 0 THEN BEGIN { Command key down }
-
- CheckKeyBuffer;
-
- IF event.what = keyDown THEN BEGIN
- AdjustMenus; { enable/disable/check menu items properly }
- DoMenuCommand( MenuKey( key ) );
- END; { if }
- END ELSE
- DoKeyDown( event );
- END; { keyDown } { call DoActivate with the window and... }
-
- activateEvt: { TRUE for activate, FALSE for deactivate }
- BEGIN
- CheckKeyBuffer;
- DoActivate( WindowPtr( event.message ), BAND( event.modifiers, activeFlag ) <> 0 );
- END;
-
- updateEvt: { call DoUpdate with the window to update }
- BEGIN
- CheckKeyBuffer;
- DoUpdate( WindowPtr( event.message ) );
- END;
-
- diskEvt:
- BEGIN
- CheckKeyBuffer; { needed here? }
- IF HiWrd(event.message) <> noErr THEN BEGIN
- SetPt(aPoint, kDILeft, kDITop);
- err := DIBadMount(aPoint, event.message);
- END;
- END;
-
- kOSEvent:
- CASE BAnd(BRotL( event.message, 8 ), $FF ) OF { high byte of message }
- kMouseMovedMessage:
- DoIdle; { mouse moved is also an idle event }
-
- kSuspendResumeMessage: BEGIN
- CheckKeyBuffer;
- gInBackground := BAnd( event.message, kResumeMask ) = 0;
- DoActivate( FrontWindow, NOT gInBackground );
- END; { kSuspendResumeMessage }
- END;
- kHighLevelEvent:
- BEGIN
- CheckKeyBuffer;
- DoHighLevelEvent(event);
- END;
- END; { case }
- END; { DoEvent }
-
-
- {$S Main}
- PROCEDURE EventLoop;
-
- {Get events forever, and handle them by calling DoEvent.
- Also call AdjustCursor each time through the loop.}
- { CHANGES FOR QUILL: initialize gQuitNow to FALSE,
- and only quit when it's been set to TRUE (by MyTerminate)
- }
- VAR
- cursorRgn : RgnHandle;
- gotEvent : BOOLEAN;
- event : EventRecord;
-
- BEGIN
- cursorRgn := NewRgn; {we'll pass an empty region to WNE the first time thru}
- gQuitNow := FALSE;
- WHILE NOT gQuitNow DO
- BEGIN
- IF gHasWaitNextEvent THEN
- gotEvent := WaitNextEvent(everyEvent, event, GetSleep, cursorRgn)
- ELSE
- BEGIN
- SystemTask;
- gotEvent := GetNextEvent(everyEvent, event);
- END;
- IF gotEvent THEN
- BEGIN
- AdjustCursor(event.where, cursorRgn);
- DoEvent(event);
- END
- ELSE DoIdle;
- AdjustCursor(event.where, cursorRgn);
- END; { of WHILE }
-
- END; {EventLoop}
-
- { NEW ROUTINES FOR QUILL (including major rewrites with new names) }
-
- {$S QuillNew2}
- FUNCTION AnythingFromListAccessor(wantClass: DescType; container: AEDesc;
- containerClass: DescType; form: DescType; selectionData: AEDesc;
- VAR value: AEDesc; theRefCon: LongInt): OSErr;
- { the OSL may return us a list of tokens. If that's the "container" from
- which we want to get a property or element, we want to return a corresponding
- list of tokens for the properties or elements.
- NOTES:
- (1) we abort on any error, even if it only involves a single item. Do we
- want to be more robust?
- (2) due to the call to AECallObjectAccessor, this is a (potentially) recursive
- routine - our list can contain embedded lists.
- (3) AppleEvents refers to "items" of a list (e.g., AECountItems). But we're already
- using "item" as a specific element of text, so we'll have to use a different class
- name (not cItem) to refer to items in a list. (That may not come up in this routine;
- I'm just thinking out loud, sort of. **CHECK) We'll still use the word "item" here,
- though.
- }
- LABEL 9;
- VAR myErr: OSErr;
- itemCount: LongInt;
- i: LongInt;
- thisItem: AEDesc;
- myToken: AEDesc;
- BEGIN
- myErr := accessorErr;
- InitSomeDescs(@value,@thisItem,@myToken,NIL,NIL);
-
- { **HACK - special-case cListElement }
- IF wantClass = cListElem THEN
- BEGIN
- myErr := ElemFromAnythingAccessor(wantClass,container,containerClass,form,selectionData,value,theRefCon);
- GOTO 9;
- END;
-
- { count the items in the list }
- IF CatchErr( AECountItems(container,itemCount) , 21213 , myErr ) THEN GOTO 9;
-
- { create the result list }
- IF CatchErr( AECreateList(NIL,0,FALSE,value) , 21214 , myErr ) THEN GOTO 9;
-
- IF itemCount = 0 THEN GOTO 9; { empty list - we're done }
-
- { loop through the items }
- FOR i := 1 TO itemCount DO
- BEGIN
- { get the item }
- IF CatchErr( AEGetNthDesc(container,i,typeWildCard,gReturnedKeywd,thisItem) , 21215 ,
- myErr ) THEN GOTO 9;
-
- { using the given selection data, and the container item that was contained, get }
- { a token for the corresponding property or element }
- { **CHECK on inputs to AECallObjectAccessor, particularly container class }
- IF CatchErr( AECallObjectAccessor(wantClass,thisItem,thisItem.descriptorType,form,
- selectionData,myToken) , 21216 , myErr ) THEN GOTO 9;
-
- { put it in the list }
- IF CatchErr( AEPutDesc(value,i,myToken) , 21217 , myErr ) THEN GOTO 9;
-
- { dispose of item and token }
- IF CatchErr( DisposeSomeDescs(@thisItem,@myToken,NIL,NIL,NIL) , 21218 , myErr ) THEN GOTO 9;
- InitSomeDescs(@thisItem,@myToken,NIL,NIL,NIL); { just for neatness, almost certainly unnecessary - **CHECK }
- END;
-
- 9: { finish up }
- IF myErr <> noErr THEN gTempBool := CheckErr( AEDisposeDesc(value) , 21219 );
- gTempBool := CheckErr( DisposeSomeDescs(@thisItem,@myToken,NIL,NIL,NIL) , 21220 );
-
- AnythingFromListAccessor := myErr;
- END; { AnythingFromListAccessor }
-
-
- {$S QuillNew }
- FUNCTION AskAboutSave(name: Str255; VAR saveFlag: BOOLEAN): BOOLEAN;
- { ask the user if we should save or not before closing; return response
- in saveFlag. Also return (as function value) whether the user
- cancelled or not.
- INPUTS: wndwTitle name of document we're asking about (used in dialog)
- saveFlag result VAR for response - TRUE if save, FALSE
- if don't save
- OUTPUTS: FALSE if the user cancelled, TRUE o.w.
- ERRORS:
- SIDE EFFECTS:
- NOTES: technically, saveFlag is undefined if the user cancels
- (although we'll set it to FALSE in that case)
- }
- VAR itemHit: INTEGER;
- BEGIN
- AskAboutSave := FALSE;
- saveFlag := FALSE;
-
- itemHit := AskUser(Concat('Save changes to "',name,'" before closing?"'));
- IF itemHit = 3 THEN EXIT(AskAboutSave); { user cancelled (3 is 'cancel') }
-
- saveFlag := (itemHit = 1); { 1 is 'yes', 2 is 'no' }
- AskAboutSave := TRUE;
- END;
-
-
- {$S QuillNew }
- FUNCTION AskBeforeClosing(window: WindowPtr; VAR saveFlag: BOOLEAN;
- VAR docFileGood: BOOLEAN; VAR fileSpec: FSSpec): BOOLEAN;
- { ask the user if he wants to save changes before closing. If yes,
- AND the window doc has a valid file spec attached to it, return
- the file spec; if yes, but no valid file spec, ask the user to
- specify a file, and return that file spec. Also give the user
- a chance to cancel the close whenever he's responding to a dialog.
- INPUTS: window ptr to the window in question
- saveFlag result VAR - TRUE if the user wants to
- save, FALSE o.w. (undefined if user cancels,
- although we'll return FALSE in that case)
- docFileGood result VAR - TRUE if docFile is a valid file
- spec (vRefNum <> badVRefNum), FALSE otherwise.
- This is just FYI; sometimes it's useful to know
- where fileSpec came from (window doc or user responses).
- (docFileGood is undefined if the user cancels or doesn't
- want to save, but we'll set it to FALSE in those cases)
- fileSpec result VAR for the file to be saved to
- (undefined if the user cancels or doesn't
- want to save, although we'll mark it as
- invalid in that case)
- OUTPUTS: TRUE if the user doesn't cancel (regardless of whether
- he saves or not), FALSE if user cancels
- ERRORS:
- SIDE EFFECTS:
- NOTES: this routine does NOT: check the window doc dirtyFlag;
- call AEInteractWithUser; save the doc itself; close the
- window itself. That's all up to the caller
- }
- VAR wndwTitle: Str255;
- BEGIN
- AskBeforeClosing := FALSE;
- saveFlag := FALSE;
- docFileGood := FALSE;
- fileSpec.vRefNum := badVRefNum;
-
- GetWTitle(window,wndwTitle);
-
- IF NOT AskAboutSave(wndwTitle,saveFlag) THEN EXIT(AskBeforeClosing); { user cancelled }
-
- IF saveFlag THEN
- BEGIN
- { user wants to save - do we have a file? }
- docFileGood := DocumentPeek(window)^.docFile.vRefNum <> badVRefNum;
- IF docFileGood THEN fileSpec := DocumentPeek(window)^.docFile { good file spec in window doc }
- ELSE
- BEGIN { we don't have a file - ask for one }
- IF NOT AskForFile(wndwTitle,fileSpec) THEN
- BEGIN
- { user cancelled }
- saveFlag := FALSE; { just for neatness }
- EXIT(AskBeforeClosing);
- END; { of user cancelling from AskForFile }
- END; { of asking for file }
- END; { of user asking to save }
-
- { if we got this far, we're fine }
- AskBeforeClosing := TRUE;
- END; { AskBeforeClosing }
-
-
- {$S QuillNew }
- FUNCTION AskForFile(name: Str255; VAR fileSpec: FSSpec): BOOLEAN;
- { ask the user to pick a file to save a document to. Return the
- file spec, and also return (as function result) whether the user
- cancelled or not.
- INPUTS: name default name for file (used in StandardFile dialog)
- fileSpec result VAR for chosen file
- OUTPUTS: FALSE if the user cancelled, TRUE o.w.
- ERRORS:
- SIDE EFFECTS:
- NOTES: if user cancels, fileSpec is undefined (although we'll
- set its vRefNum to badVRefNum in that case, for neatness)
- }
- VAR mySFReply: StandardFileReply;
- BEGIN
- AskForFile := FALSE;
- fileSpec.vRefNum := badVRefNum;
-
- StandardPutFile(Concat('Save "',name,'" as: '),name,mySFReply);
- WITH mySFReply DO
- BEGIN
- IF NOT sfGood THEN EXIT(AskForFile); { user cancelled }
- fileSpec := sfFile;
- END;
-
- AskForFile := TRUE;
- END;
-
- {$S QuillNew}
- FUNCTION AskUser( question: Str255 ): INTEGER;
-
- { put up an Alert to ask the user a question,
- with possible responses yes, no, or cancel
-
- INPUTS: question text of the question
- OUTPUTS: 1 for yes, 2 for no, 3 for cancel
- ERRORS:
- SIDE EFFECTS:
- }
- BEGIN { AskUser }
- SetCursor( arrow );
- ParamText(question, '', '', '');
- AskUser := Alert( rYesOrNo, NIL );
- END; { AskUser }
-
- {$S QuillNew}
- FUNCTION BackWindow: WindowPtr;
- { returns a ptr to the last window in the back-to-front
- ordering. If there are nu current windows, returns NIL.
- INPUTS: none
- OUTPUTS: ptr to last window (NIL if no windows)
- }
- LABEL 9;
- VAR window: WindowPtr;
- nextWndw: WindowPtr;
- BEGIN
- window := FrontWindow;
- IF window = NIL THEN GOTO 9; { no windows - go finish up }
- WHILE TRUE DO { repeat forever, sort of }
- BEGIN
- nextWndw := WindowPtr(WindowPeek(window)^.nextWindow);
- IF nextWndw = NIL THEN GOTO 9; { got last window, it's in "window" - go finish up }
- window := nextWndw; { try the next one }
- END;
-
- 9: { finish up }
- BackWindow := window;
- END; { BackWindow }
-
-
- {$S QuillNew }
- FUNCTION BoolToStr(theBool: BOOLEAN): Str15;
- BEGIN
- IF theBool THEN BoolToStr := 'TRUE' ELSE BoolToStr := 'FALSE';
- END; { BoolToStr }
-
- {$S QuillNew}
- FUNCTION CatchErr(theErr: OSErr; placeNum: INTEGER; VAR holdErr: OSErr): BOOLEAN;
- { if theErr <> noErr, then put up an error alert and return TRUE; o.w. return
- FALSE (no alert). In either case, return theErr in holdErr for future use.
- This is just like CheckErr except that it also saves the err; see CheckErr and
- DoMyErr for more details.
- INPUTS: theErr potential error to be checked and reported
- placeNum number to mark actual place of error in code; should be unique
- VAR holdErr variable to store error number
- OUTPUTS: TRUE if theErr is an error (not noErr), FALSE o.w.
- ERRORS:
- SIDE EFFECTS: will put up error alert if theErr <> noErr
- }
- BEGIN
- holdErr := theErr;
- CatchErr := CheckErr(theErr,placeNum);
- END; { CatchErr }
-
- {$S QuillNew}
- PROCEDURE CheckKeyBuffer;
- { check to see if the key buffer is empty and, if
- it's not, ship it off in a Set Data event so we
- can record the typing represented by it. Then
- clear the buffer.
- INPUTS: none
- OUTPUTS: none
- NOTES: (1) very preliminary, especially the error-handling
- (2) IMPORTANT: we ship out the characters FOR RECORDING
- PURPOSES ONLY - we've already handled the changing of
- text in real-time, when the user did the typing
- ( **CHECK - Ed, how do we mark things "for recording only"?)
- 10/03/91 BHM experimental change to use "smart" recording (when feasible)
- }
- LABEL 9;
- VAR tempErr: OSErr;
- textDesc: AEDesc;
- wndwIndex: INTEGER;
- origSelObj: AEDesc;
- myAppleEvent: AppleEvent;
- defReply: AppleEvent;
- BEGIN
- { fast exit if key buffer empty }
- IF keyBuffer.bufEmpty THEN EXIT(CheckKeyBuffer);
-
- { we've got some keystrokes to ship out }
- { NOTE: due to the special handling of Delete characters, we may in fact }
- { have no actual characters to send; the Delete characters may have cancelled }
- { the normal characters. But we still have to record the deletion of the }
- { selection (which would still occur even in the case of this "cancelling"), }
- { so we still have to send a Set Data event. }
-
- InitSomeDescs(@textDesc,@origSelObj,@myAppleEvent,@defReply,NIL);
-
- WITH keyBuffer DO
- BEGIN
-
- { create a descriptor for text in the buffer }
- HLock(Handle(bufChars));
- tempErr := AECreateDesc(typeChar,Handle(bufChars)^,bufCharCount,textDesc);
- HUnlock(Handle(bufChars));
- IF CheckErr( tempErr , 19313 ) THEN GOTO 9;
-
- { now do some work on the selection AS IT WAS WHEN THE USER STARTED TYPING }
-
- { **CHECK - EXPERIMENTAL - 10/3/91: }
- { If there are no "uncancelled" Delete chars, then the selection obj recorded }
- { when we started buffering is good - and it uses "smart" recording }
-
- IF bufDelCount = 0 THEN
- BEGIN
- { I'll take the easy way out and just copy it over, for now }
- IF CheckErr( AEDuplicateDesc(bufDesc,origSelObj) , 19321 ) THEN GOTO 9;
- END
-
- ELSE
-
- BEGIN
- { uncancelled Deletes case }
-
- { first, adjust for "uncancelled" Delete chars (if any) }
- bufSelStart := bufSelStart - bufDelCount;
- IF bufSelStart < 0 THEN bufSelStart := 0; { can't have a negative char position }
-
- { now make on object for the old (but adjusted) selection }
-
- wndwIndex := IndexFromWndwPtr(bufWndw);
- { **CHECK for 0? or, for that matter - check for 1 (it should always be 1 . . .) }
- IF bufSelStart = bufSelEnd THEN
- BEGIN
- IF CheckErr( MakeSpotObj(wndwIndex,bufSelStart+1,origSelObj) , 19314 ) THEN GOTO 9;
- END
- ELSE
- BEGIN
- IF CheckErr( MakeTextRangeObj(wndwIndex,bufSelStart+1,bufSelEnd,origSelObj) , 19315 ) THEN GOTO 9;
- END;
-
- END; { uncancelled Deletes case }
-
- { NOTE: the "+1's" are in there because selections are internally represented starting from 0, but }
- { objects are counted starting from 1 }
- END; { of WITH keyBuffer }
-
- { create the AppleEvent }
- IF CheckErr( AECreateAppleEvent(kAECoreSuite,kAESetData,gSelfAddrDesc,kAutoGenerateReturnID,kAnyTransactionID,
- myAppleEvent) , 19316 ) THEN GOTO 9;
-
- { add the direct object }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyDirectObject,origSelObj) , 19317 ) THEN GOTO 9;
-
- { add the data }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyAEData,textDesc) , 19318 ) THEN GOTO 9;
-
- { **CHECK - must set bufEmpty = TRUE before sending the Set Data }
- { event, because the event itself will set off this routine . . . ??!*? }
-
- keyBuffer.bufEmpty := TRUE;
-
- { send the event }
- gTempBool := CheckErr( AESend(myAppleEvent,defReply,kAENoReply+kAEAlwaysInteract+kAEDontExecute,kAENormalPriority,
- kAEDefaultTimeOut,NIL,NIL) , 19319 );
-
- { ShowTyping(textDesc);}
-
- 9: { finish up }
-
- gTempBool := CheckErr( DisposeSomeDescs(@textDesc,@origSelObj,@myAppleEvent,@defReply,NIL) , 19320 );
-
- ResetKeyBuffer;
- END; { CheckKeyBuffer }
-
-
- {$S QuillNew}
- FUNCTION CheckErr(theErr: OSErr; placeNum: INTEGER): BOOLEAN;
- { if theErr <> noErr, then put up an error alert (including err num
- and placeNum) and return TRUE; o.w. just return FALSE (with no alert). This
- is meant to be used with error-returning function calls (e.g., all AE routines)
- in the first parameter. See DoMyErr for more details.
- INPUTS: theErr potential error to be checked and reported
- placeNum number to mark actual place of error in code; should be unique
- OUTPUTS: TRUE if theErr is an error (not noErr), FALSE o.w.
- ERRORS:
- SIDE EFFECTS: will put up error alert if theErr <> noErr
- }
- BEGIN
- CheckErr := FALSE;
- IF theErr <> noErr THEN
- BEGIN
- DoMyErr(theErr,placeNum);
- CheckErr := TRUE;
- END;
- END; { CheckErr }
-
- {$S QuillNew}
- PROCEDURE CleanWindow(window: WindowPtr);
- { mark the given window as not dirty
- INPUTS: window ptr to the window
- OUPUTS: none
- }
- BEGIN
- DocumentPeek(window)^.dirtyFlag := FALSE;
- END; { CleanWindow }
-
- {$S QuillNew }
- FUNCTION CloseAllAskUser(VAR userCancelled: BOOLEAN): OSErr;
- { close the windows one at a time. For each dirty window,
- ask the user if she wants to save; also give her a chance
- to cancel out. Call AEInteractWithUser before putting up
- a dialog; if interaction is impossible, abort with
- appropriate error code
- INPUTS: userCancelled result VAR - TRUE if the user
- cancelled, FALSE o.w. (undefined
- if call fails, but we'll set it
- to FALSE in that case)
- OUTPUTS: error number (noErr if none). User cancellation
- is NOT an error.
- ERRORS:
- SIDE EFFECTS:
- }
- LABEL 8,9;
- VAR myErr: OSErr;
- window: WindowPtr;
- saveFlag: BOOLEAN;
- docFileGood: BOOLEAN;
- fileSpec: FSSpec;
- BEGIN
- myErr := genericErr;
- userCancelled := FALSE;
-
- window := FrontWindow;
- WHILE window <> NIL DO
- BEGIN
- IF WindowIsDirty(window) THEN
- BEGIN
- { dirty window - should we save? }
- IF CatchErr( AEInteractWithUser(kNoTimeOut,NIL,NIL) , 8513 , myErr )
- THEN GOTO 9; { couldn't interact - go set function value }
-
- { we're IN-TER-ACT-ING!!! }
- userCancelled := NOT AskBeforeClosing(window,saveFlag,docFileGood,fileSpec);
- IF userCancelled THEN GOTO 8; { noErr exit }
-
- IF saveFlag THEN
- IF CatchErr( GetFileAndSaveWndw(window,TRUE,fileSpec) , 8514 , myErr )
- THEN GOTO 9; { trouble with the save }
- END; { of dirty window }
- ShutTheWindow(window);
- window := WindowPtr(WindowPeek(window)^.nextWindow);
- END; { of WHILE loop }
-
- { everything looks fine }
- 8: { noErr exit }
- myErr := noErr;
-
- 9: { set function value }
- CloseAllAskUser := myErr;
- END; { CloseAllAskUser }
-
- {$S QuillNew }
- PROCEDURE CloseAllNoSave;
- { close all windows, don't save any of them
- INPUTS: none
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- VAR window: WindowPtr;
- BEGIN
- window := FrontWindow;
- WHILE window <> NIL DO
- BEGIN
- ShutTheWindow(window);
- window := WindowPtr(WindowPeek(window)^.nextWindow);
- END;
- END; { CloseAllNoSave }
-
- {$S QuillNew }
- FUNCTION CloseAllWithSave: OSErr;
- { close all windows, save all the dirty ones - don't
- interact with user. We use GetFileAndSaveWndw, which
- (in this case) first tries the window's docFile, if
- it's valid, and then tries to concoct a file from
- the window title and the current default volume
- and path.
- INPUTS: none
- OUTPUTS: error code (noErr if none) - file-and-mem
- problems, generally
- ERRORS:
- SIDE EFFECTS:
- }
- LABEL 9;
- VAR myErr: OSErr;
- window: WindowPtr;
- fileSpec: FSSpec;
- BEGIN
- myErr := genericErr;
- window := FrontWindow;
- WHILE window <> NIL DO
- BEGIN
- IF WindowIsDirty(window) THEN
- IF CatchErr( GetFileAndSaveWndw(window,FALSE,fileSpec) , 8414 , myErr ) THEN
- GOTO 9; { save failed - go set function value }
- ShutTheWindow(window);
- window := WindowPtr(WindowPeek(window)^.nextWindow);
- END;
-
- { everything looks fine }
- myErr := noErr;
-
- 9: { set function value }
- CloseAllWithSave := myErr;
- END; { CloseAllWithSave }
-
- {$S QuillNew2}
- FUNCTION CloseToken(theToken: AEDesc; saveOpt: DescType; gotDestFile: BOOLEAN;
- destFile: FSSpec): OSErr;
- { this routine takes a single token (not a list) and closes the object it
- represents. Right now we only know how to close windows and documents.
- INPUTS: theToken token representing the object to be closed
- saveOpt parameter describing whether or not to save "dirty"
- object: kAEYes (save), kAENo (don't save), or
- kAEAsk (ask user)
- gotDestFile TRUE if file to be saved to is specified, FALSE o.w.
- destFile a file to save the document to
- OUTPUTS: error code (noErr if none)
- NOTES: (1) if saveOpt is not kAEYes, then gotDestFile and destFile are ignored;
- if gotDestFile is FALSE, then destFile is ignored.
- (2) we do not validate saveOpt here; that should be done higher up
- }
- LABEL 9;
- VAR myErr: OSErr;
- myWndw: WindowPtr;
- saveFlag: BOOLEAN;
- myFSS: FSSpec;
- BEGIN
- myErr := genericErr;
-
- { token must be window or doc }
- IF (theToken.descriptorType <> typeMyWndw) & (theToken.descriptorType <> typeMyDoc) THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 24013 , myErr );
- GOTO 9;
- END;
-
- { get the window/doc }
- IF CatchErr( MyAECoerceDescPtr(theToken,typeWildCard,@myWndw,SizeOf(myWndw),gActSize) ,
- 24014 , myErr ) THEN GOTO 9;
-
- { if it's dirty, you may have to save }
- IF WindowIsDirty(myWndw) & (saveOpt <> kAENo) THEN
- BEGIN
-
- IF saveOpt = kAEAsk THEN
- BEGIN
- { have to ask user about saving }
- IF CatchErr( AEInteractWithUser(kNoTimeOut,NIL,NIL) , 24015 , myErr ) THEN GOTO 9;
- IF NOT AskBeforeClosing(myWndw,saveFlag,gTempBool,myFSS) THEN
- BEGIN
- { user cancelled }
- myErr := errAEUserCancelled;
- GOTO 9;
- END;
- IF saveFlag THEN
- IF CatchErr( GetFileAndSaveWndw(myWndw,TRUE,myFSS) , 24016 , myErr ) Then GOTO 9; { trouble with the save }
- END { of kAEAsk case }
-
- ELSE IF saveOpt = kAEYes THEN
- BEGIN
- { save, without bothering the user }
- IF CatchErr( GetFileAndSaveWndw(myWndw,gotDestFile,destFile) , 24017 , myErr ) THEN GOTO 9;
- END; { of kAEYes case }
-
- END; { of having to save the window }
-
- { now shut it }
- ShutTheWindow(myWndw);
-
- 9:
- CloseToken := myErr;
- END; { CloseToken }
-
- {$S QuillNew2}
- FUNCTION CloseTokenList(theList: AEDesc; saveOpt: DescType; gotDestFile: BOOLEAN;
- destFile: FSSpec): OSErr;
- { this routine takes a list of tokens (or, more precisely, whose ultimate
- nodes are tokens; we permit lists of lists, etc.), and closes everything
- on the list. Actually, it just walks through the list and, when it gets
- to tokens, passes them to CloseToken.
- The input parameters are passed unchanged to CloseToken; see that routine
- for descriptions. The gotDestFile and destFile parameters don't really
- make much sense for a list (you would wind up saving everything in the
- list to the same destFile); perhaps in the future we'll permit a list
- of dest files.
- If we hit an error at any point, we abort the operation; we don't try
- to continue with other items in the list.
-
- INPUTS: see CloseToken
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- itemCount: LongInt;
- i: LongInt;
- thisItem: AEDesc;
- BEGIN
- myErr := genericErr;
- thisItem := gNullDesc;
-
- IF CatchErr( AECountItems(theList,itemCount) , 23013 , myErr ) THEN GOTO 9;
- IF itemCount = 0 THEN GOTO 9; { empty list, we're done }
-
- { loop through the items }
- FOR i := 1 TO itemCount DO
- BEGIN
- { get the item }
- IF CatchErr( AEGetNthDesc(theList,i,typeWildCard,gReturnedKeywd,thisItem) , 23014 ,
- myErr ) THEN GOTO 9;
-
- { dispatch on list vs. non-list }
- IF thisItem.descriptorType = typeAEList THEN
- BEGIN
- IF CatchErr( CloseTokenList(thisItem,saveOpt,gotDestFile,destFile) , 23015 , myErr )
- THEN GOTO 9;
- END
- ELSE
- BEGIN
- IF CatchErr( CloseToken(thisItem,saveOpt,gotDestFile,destFile) , 23016 , myErr )
- THEN GOTO 9;
- END;
-
- { dispose of item }
- gTempBool := CheckErr( AEDisposeDesc(thisItem) , 23017 );
- thisItem := gNullDesc;
- END; { FOR loop }
-
- 9:
- gTempBool := CheckErr( AEDisposeDesc(thisItem) , 23018 );
- CloseTokenList := myErr;
- END; { CloseTokenList }
-
-
- {$S QuillNew2}
- FUNCTION CoerceListOrValToTextStyles(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr;
- { this takes a list, presumably of style item constants, and creates
- a style desc (of typeTextStyles) that has that list for its "on"
- styles and an empty list for the "off" styles; this is convenient
- when you want to say "set the style of some text to [bold, underline]"
- and not specify the full style desc. It does no validity checking;
- if the list is not valid, the problem will get caught when any routine
- tries to use the resulting style desc.
-
- The routine will also take a single enumerated value (presumably a
- style item constant), which it coerces to a single-item list and then
- to a style desc. Again, no validity checking is done.
-
- kAEPlain is a valid style item const here.
- }
- LABEL 9;
- VAR myErr: OSErr;
- newDesc: AEDesc;
- listDesc: AEDesc; { doesn't need to be initialized or disposed - it's a "pure copy" }
- styleRec: AEDesc;
- offList: AEDesc;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@result,@styleRec,@offList,@newDesc,NIL);
-
- IF theAEDesc.descriptorType <> typeAEList THEN
- BEGIN
- { must be enumerated value; coerce to list }
- IF CheckErr( AECoerceDesc(theAEDesc,typeAEList,newDesc) , 22613 ) THEN GOTO 9;
- listDesc := newDesc;
- END
- ELSE listDesc := theAEDesc; { CAREFUL! - don't dispose of listDesc! }
-
- { create the record for text styles desc }
- IF CatchErr( AECreateList(NIL,0,TRUE,styleRec) , 22613 , myErr ) THEN GOTO 9;
-
- { attach this list }
- IF CatchErr( AEPutKeyDesc(styleRec,keyAEOnStyles,theAEDesc) , 22614 , myErr ) THEN GOTO 9;
-
- { create empty list for "off" }
- IF CatchErr( AECreateList(NIL,0,FALSE,offList) , 22615 , myErr ) THEN GOTO 9;
-
- { attach it }
- IF CatchErr( AEPutKeyDesc(styleRec,keyAEOffStyles,offList) , 22616 , myErr ) THEN GOTO 9;
-
- { coerce record to typeTextStyles }
- gTempBool := CatchErr( AECoerceDesc(styleRec,typeTextStyles,result) , 22617 , myErr);
-
- 9:
- gTempBool := CheckErr( DisposeSomeDescs(@styleRec,@offList,@newDesc,NIL,NIL) , 22618 );
-
- CoerceListOrValToTextStyles := myErr;
- END; { CoerceListOrValToTextStyles }
-
- {$S QuillNew2}
- FUNCTION CoerceMyDocToMyWndw(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr;
- { we can't make docs and windows EXACTLY the same because pClass
- is different for them (and there may be one or two other things
- that come along, too) - but generally we would like to let someone
- ask for a typeMyWndw regardless of whether we started from cWindow
- or cDocument
- }
- LABEL 9;
- VAR myErr: OSErr;
- BEGIN
- myErr := genericErr;
- result := gNullDesc;
- IF CatchErr( AEDuplicateDesc(theAEDesc,result) , 21413 , myErr ) THEN GOTO 9;
- result.descriptorType := typeMyWndw;
- 9:
- CoerceMyDocToMyWndw := myErr;
- END; { CoerceMyDocToMyWndw }
-
- {$S QuillNew}
- FUNCTION CoerceMyTextToStylText(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- myText: TextToken;
- BEGIN
- myErr := genericErr;
- result := gNullDesc;
- IF CatchErr( MyAECoerceDescPtr(theAEDesc,typeMyText,@myText,SizeOf(myText),gActSize) , 17313 , myErr )
- THEN GOTO 9;
- gTempBool := CatchErr( MakeStylTextDesc(myText,result) , 17314 , myErr);
- 9:
- CoerceMyTextToStylText := myErr;
- END; { CoerceMyTextToStylText }
-
-
-
- {$S QuillNew}
- FUNCTION CoerceObjToAnything(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- objDesc: AEDesc;
- BEGIN
- myErr := errAECoercionFail;
- InitSomeDescs(@result,@objDesc,NIL,NIL,NIL);
-
- { check a type for robustness' sake }
- IF theAEDesc.descriptorType <> typeObjectSpecifier THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 1813 , myErr );
- GOTO 9;
- END;
-
- { resolve the object specifier }
- IF QuietCatchErr( AEResolve(theAEDesc,kAEIDoMinimum,objDesc) , myErr )
- THEN GOTO 9;
- { hopefully it's the right type by now, but we'll give it a nudge }
- IF QuietCatchErr( AECoerceDesc(objDesc,toType,result) , myErr )
- THEN GOTO 9;
- { looks good to me }
- myErr := noErr;
-
- 9: { finish up }
- gTempBool := CheckErr( AEDisposeDesc(objDesc) , 1814 );
-
- { NOTE: even if myErr <> noErr, we don't have to dispose of result
- because nothing after result is created can generate an error. Of
- course, if myErr = noErr, then you CERTAINLY don't want to dispose
- of result; you want to return it. }
-
- CoerceObjToAnything := myErr;
- END; { CoerceObjToAnything }
-
- {$S QuillNew}
- FUNCTION CoerceStylTextToText(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- newDesc: AEDesc;
- BEGIN
- myErr := errAECoercionFail;
- newDesc := gNullDesc;
- { some checks for robustness' sake }
- IF theAEDesc.descriptorType <> typeStyledText THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 13413 , myErr );
- GOTO 9;
- END;
-
- IF toType <> typeChar THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 13414 , myErr );
- GOTO 9;
- END;
-
- { convert the descriptor to typeAERecord }
- IF CatchErr( AECoerceDesc(theAEDesc,typeAERecord,newDesc) , 13418 , myErr)
- THEN GOTO 9;
-
- { get the text desc out of the record }
- gTempBool := CatchErr( AEGetKeyDesc(newDesc,keyAEText,typeChar,result) , 13415 , myErr );
-
- 9: { finish up }
- gTempBool := CheckErr( AEDisposeDesc(newDesc) , 13417 );
- CoerceStylTextToText := myErr;
- END; { CoerceStylTextToText }
-
- {$S QuillNew}
- FUNCTION CoerceStylTextToIntlText(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr;
- { NOTE: I hard-code the script and language codes here. I've also skipped
- the robustness checks. Who needs 'em?!??
- }
- LABEL 9;
- VAR myErr: OSErr;
- stylTextRec: AEDesc;
- textDesc: AEDesc;
- BEGIN
- myErr := errAECoercionFail;
- InitSomeDescs(@result,@stylTextRec,@textDesc,NIL,NIL);
-
- { convert the descriptor to typeAERecord }
- IF CatchErr( AECoerceDesc(theAEDesc,typeAERecord,stylTextRec) , 23313 , myErr )
- THEN GOTO 9;
-
- { get the text out }
- IF CatchErr( AEGetKeyDesc(stylTextRec,keyAEText,typeChar,textDesc) , 23314 , myErr )
- THEN GOTO 9;
-
- { make it into typeIntlText }
- gTempBool := CatchErr( TextToIntlText(textDesc,smRoman,langEnglish,result) , 23315 , myErr );
-
- 9:
-
- gTempBool := CheckErr( DisposeSomeDescs(@stylTextRec,@textDesc,NIL,NIL,NIL) , 23316 );
-
- CoerceStylTextToIntlText := myErr;
- END; { CoerceStylTextToIntlText }
-
- {$S QuillNew2}
- FUNCTION CoerceIntlTextToText(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr;
- { NOTE: I throw away the script/language codes here. I've also
- skipped any robustness checks.
- }
- BEGIN
- CoerceIntlTextToText := IntlTextToText(theAEDesc,result,gTempInt,gTempInt);
- END; { CoerceIntlTextToText }
-
- {$S QuillNew2}
- FUNCTION CoerceTextToIntlText(theAEDesc: AEDesc; toType: DescType;
- handlerRefCon: LongInt; VAR result: AEDesc): OSErr;
- { NOTE: I hard-code the script/language codes here. I've also
- skipped any robustness checks.
-
- I'm not actually sure I NEED this routine anywhere.
- }
- BEGIN
- CoerceTextToIntlText := TextToIntlText(theAEDesc,smRoman,langEnglish,result);
- END; { CoerceTextToIntlText }
-
-
- {$S QuillNew}
- FUNCTION CompareTextDescs(text1: AEDesc; text2: AEDesc; VAR result: DescType): OSErr;
- { this routine compares two pieces of text, given by descriptors of typeChar,
- and returns an ordering relation: either kAEEquals, kAEGreaterThan, or
- kAELessThan
- INPUTS: text1 descriptor for first piece of text
- text2 descriptor for second piece of text
- result return VAR for comparison result, expressed as a DescType
- OUTPUTS: error code (noErr if none)
- NOTES: first we use EqualString to see if the texts are equal to at least
- 255 characters, ignoring case but not diacriticals. If they're equal
- by that test, we return kAEEqual. Otherwise we turn to IUMagString
- (which looks at all the characters, but unfortunately is sensitive
- to case as well as diacriticals) to get the ordering.
- **CHECK - this is a mixed-bag string-ordering system, used for
- convenience; we may want to improve it later.
- }
- LABEL 9;
- VAR myErr: OSErr;
- text1Str: Str255;
- text2Str: Str255;
- text1Ptr: Ptr;
- text1Len: LongInt;
- text2Ptr: Ptr;
- text2Len: LongInt;
- iuRes: INTEGER;
- BEGIN
- myErr := genericErr;
-
- { turn the text into strings }
- IF CatchErr( TextDescToStr(text1,text1Str,gActSize) , 16013 ,myErr )
- THEN GOTO 9;
-
- IF CatchErr( TextDescToStr(text2,text2Str,gActSize) , 16014 ,myErr )
- THEN GOTO 9;
-
- IF EqualString(text1Str,text2Str,FALSE,TRUE) THEN { ignoring case but not diacriticals }
- BEGIN
- result := kAEEquals;
- GOTO 9;
- END;
-
- { they weren't equal with EqualString; use IUMagString to get ordering }
-
- WITH text1 DO
- BEGIN
- HLock(dataHandle);
- text1Ptr := dataHandle^;
- text1Len := GetHandleSize(dataHandle);
- END;
-
- WITH text2 DO
- BEGIN
- HLock(dataHandle);
- text2Ptr := dataHandle^;
- text2Len := GetHandleSize(dataHandle);
- END;
-
- iuRes := IUMagString(text1Ptr,text2Ptr,text1Len,text2Len);
-
- IF iuRes = -1 THEN result := kAELessThan
- ELSE IF iuRes = 0 THEN result := kAEEquals { can this even happen, since the first 255 chars were not equal under EqualString? }
- ELSE result := kAEGreaterThan;
-
- HUnlock(text1.dataHandle);
- HUnlock(text2.dataHandle);
-
- myErr := noErr;
-
- 9: { finish up }
-
- CompareTextDescs := myErr;
- END; { CompareTextDescs }
-
- { $S QuillNew2}
- PROCEDURE ContinueKeyBuffering(key: CHAR; window: WindowPtr);
- { this routine is called to add a character (normal or delete)
- to the key buffer when the buffer is "not empty" - or, more
- precisely, after one or more typed characters has been entered
- into the buffer. Due to the special handling of Delete characters,
- there may be zero characters in the buffer at this time (if
- Delecte chars have cancelled out normal chars), but the buffer
- is not considered empty (because it has recorded some key events).
- See StartKeyBuffering for more detail.
- INPUTS: key the character that's been typed
- window ptr to the window being typed into (only used
- for robustness checking)
- OUTPUTS: none
- NOTES: we may want to do more sophisticated error handling
- }
- BEGIN
- WITH keyBuffer DO
- BEGIN
-
- IF bufEmpty THEN
- BEGIN
- DoMyAlert('Trouble - ContinueKeyBuffering called with empty buffer!');
- EXIT(ContinueKeyBuffering);
- END;
-
- IF window <> bufWndw THEN
- BEGIN
- DoMyAlert('Trouble - windows do not match in ContinueKeyBuffering!');
- EXIT(ContinueKeyBuffering);
- END;
-
- IF key = CHR(kDelChar) THEN
- BEGIN
- { Delete char - if there are normal chars in the buffer, drop one; otherwise }
- { increase the count of "uncancelled" Delete's }
- IF bufCharCount = 0 THEN bufDelCount := bufDelCount + 1 ELSE bufCharCount := bufCharCount - 1;
- EXIT(ContinueKeyBuffering);
- END;
-
- { if we get this far, it's a normal character }
- IF bufCharCount >= bufSize THEN
- BEGIN
- IF NOT GrowKeyBuffer THEN
- BEGIN
- DoMyAlert('Trouble in ContinueKeyBuffering - out of memory!'); { this is a true error and should be handled better }
- EXIT(ContinueKeyBuffering);
- END;
- END;
-
- { we have room - add the character }
- bufChars^^[bufCharCount] := key;
- bufCharCount := bufCharCount + 1;
- END; { of WITH keyBuffer }
-
- END; { of ContinueKeyBuffering }
-
-
-
- {$S QuillNew}
- FUNCTION CountDelChars(textPtr: Ptr; textLength: LongInt;
- delChar: SignedByte): LongInt;
- { count the occurrences of a particular character in a piece
- of text given by ptr and length. We talk about the char as
- "delChar" because this routine is aminly used to count delimiter
- characters (CR for lines, comma for items), but any character
- can be used.
- INPUTS: textPtr ptr to the start of the text
- textLength length of the text
- delChar ascii value of the char to be counted
- OUTPUTS: number of occurrences of the delChar in the text
- NOTES: when using this routine to get the number of lines
- or items in some text, remember that the number of
- lines/items is ONE MORE than the number of CRs/commas
- (e.g., a string with no CRs still has one line)
- }
- VAR endPlus1Ptr: Ptr;
- count: LongInt;
- BEGIN
- endPlus1Ptr := Ptr(ORD(textPtr) + textLength); { ptr to 1 byte beyond the end of the text }
- count := 0;
- WHILE textPtr <> endPlus1Ptr DO
- BEGIN
- IF textPtr^ = delChar THEN count := count + 1;
- textPtr := Ptr(ORD(textPtr) + 1);
- END;
- CountDelChars := count;
- END; { CountDelChars }
-
- {$S QuillNew}
- FUNCTION CountTextElems(srcText: TextToken; elemClass: DescType;
- VAR elemCount: LongInt): OSErr;
- { this routine counts the number of text elements of a given class -
- chars, words, lines, or items - contained in a given piece of text
- specified by a text token.
- INPUTS: srcText the text
- elemClass class of the text element to be counted
- elemCount return VAR number of elements of that class
- OUTPUTS: error code (noErr if none). Currently the only possible
- error is errAEWrongDataType, indicating an illegal elemClass
- NOTES: unfortunately, we can't do a CASE statement on elemClass
- with our current Pascal compiler
- 7/1/91 BHM Added "spots"
- }
- LABEL 9;
- VAR myErr: OSErr;
- textHndl: Handle;
- textPtr: Ptr;
- textLength: LongInt;
- BEGIN
- myErr := genericErr;
- elemCount := -1; { illegal value, easily recognized }
-
- IF elemClass = cChar THEN
- BEGIN
- elemCount := srcText.tokenLength; { this is easy . . . . }
- myErr := noErr;
- GOTO 9; { finish up }
- END;
-
- IF elemClass = cSpot THEN
- BEGIN
- elemCount := srcText.tokenLength + 1;
- myErr := noErr;
- GOTO 9;
- END;
-
- WITH srcText DO
- BEGIN
- textHndl := DocumentPeek(tokenWndw)^.docTE^^.hText;
- HLock(textHndl);
- textPtr := Ptr(ORD(textHndl^) + tokenOffset);
- textLength := tokenLength;
- END;
-
- myErr := noErr; { rare to put this in the middle, but it makes sense here }
-
- IF elemClass = cWord THEN elemCount := CountWords(textPtr,textLength)
- ELSE IF elemClass = cLine THEN elemCount := CountDelChars(textPtr,textLength,asciiCR) + 1
- ELSE IF elemClass = cItem THEN elemCount := CountDelChars(textPtr,textLength,asciiComma) + 1
- ELSE myErr := errAEWrongDataType; { illegal element class }
-
- HUnlock(textHndl);
-
- 9: { finish up }
-
- CountTextElems := myErr;
- END; { CountTextElems }
-
-
- {$S QuillNew}
- FUNCTION CountWindows: INTEGER;
- { count the number of currently open windows
- INPUTS: none
- OUTPUTS: the number of windows
- ERRORS:
- SIDE EFFECTS:
- }
- VAR i: INTEGER;
- window: WindowPtr;
- BEGIN
- i := 0;
- window := FrontWindow;
- WHILE window <> NIL DO
- BEGIN
- i := i+1;
- window := WindowPtr(WindowPeek(window)^.nextWindow);
- END;
- CountWindows := i;
- END; { CountWindows }
-
- {$S QuillNew}
- FUNCTION CountWords(textPtr: Ptr; textLength: LongInt): LongInt;
- { count the number of words in a piece of text.
-
- A word is any stretch of contiguous bytes that contains no break characters,
- is of positive length, and is bounded by break characters and/or the start
- of the text and/or the end of the text. Even text with no break characters
- can contain a word (the text "alpha" has 1 word). However, some text contains
- no words at all, e.g. a run of 17 spaces. Text with 0 length contains no words.
- By definition a word cannot be of length 0.
-
- Break characters are defined by the routines ScanToBreak and ScanToNonBreak.
- As currently implemented, they think spaces and carriage returns are breaks,
- and nothing else.
-
- INPUTS: textPtr ptr to the text
- textLength length of the text
- OUTPUTS: number of words in the text
- }
- LABEL 9;
- VAR count: LongInt;
- endPtr: Ptr;
- endPlus1Ptr: Ptr;
- wordPtr: Ptr;
- breakPtr: Ptr;
- BEGIN
- count := 0;
-
- IF textLength = 0 THEN GOTO 9; { finish up }
-
- endPtr := Ptr(ORD(textPtr) + textLength - 1); { ptr to last char of the text }
- endPlus1Ptr := Ptr(ORD(endPtr) + 1); { useful to have around }
-
- { go to start of first word }
- ScanToNonBreak(textPtr,endPtr,wordPtr);
-
- IF wordPtr = endPlus1Ptr THEN GOTO 9; { there wasn't any first word }
-
- count := 1;
-
- WHILE TRUE DO { loop forever, sort of }
- BEGIN
- ScanToBreak(wordPtr,endPtr,breakPtr);
- IF breakPtr = endPlus1Ptr THEN GOTO 9; { no more break chars, so no more words }
-
- { go to start of next word }
- ScanToNonBreak(breakPtr,endPtr,wordPtr);
- IF wordPtr = endPlus1Ptr THEN GOTO 9; { there wasn't a next word }
-
- { sure there is }
- count := count + 1;
- END;
-
- 9: { finish up }
- CountWords := count;
- END; { CountWords }
-
- {$S QuillNew2}
- FUNCTION DecodeInsertionLoc(insertionLoc: AEDesc; VAR relObjToken: AEDesc;
- VAR position: DescType): OSErr;
- { this routine takes a descriptor of typeInsertionLoc and breaks it
- up into its constituent parts, the object (which can either be an
- object to put something before, after, or into (replace), OR a container
- to put something at the beginning or end of) and the position (which
- specifies either before, after, or replace, OR beginning of or end of).
- The object is resolved to a token (possibly the null descriptor, for
- the app's "default container").
-
- INPUTS: insertionLoc a descriptor of typeInsertionLoc
- relObjToken return VAR for token representing the object
- field of the insertion loc
- position return VAR for enumerated value specifying
- the position relative to the object (before/after/
- replace, or beginning/end)
- OUTPUTS: error code (noErr if none)
- NOTES: (1) the object field must resolve to a single item, not a list
- }
- LABEL 9;
- VAR myErr: OSErr;
- newRec: AEDesc;
- objDesc: AEDesc;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@relObjToken,@objDesc,@newRec,NIL,NIL);
- position := kAEBefore;
-
- { coerce insertion loc to AERecord }
- IF CatchErr( AECoerceDesc(insertionLoc,typeAERecord,newRec) , 20421 , myErr )
- THEN GOTO 9;
-
- { get position }
- IF CatchErr( AEGetKeyPtr(newRec,keyAEPosition,typeEnumerated,gReturnedType,@position,
- SizeOf(position),gActSize) , 20413 , myErr ) THEN GOTO 9;
-
- { validate it }
- IF (position <> kAEBefore) & (position <> kAEAfter) & (position <> kAEReplace) &
- (position <> kAEBeginning) & (position <> kAEEnd) THEN
- BEGIN
- gTempBool := CatchErr( errAEBadData , 20414 , myErr );
- GOTO 9;
- END;
-
- { get object }
- IF CatchErr( AEGetKeyDesc(newRec,keyAEObject,typeWildCard,objDesc) , 20415 ,
- myErr ) THEN GOTO 9;
-
- { check for null }
- IF objDesc.descriptorType = typeNull THEN relObjToken := gNullDesc
- ELSE
- BEGIN
- { better be an object spec }
- IF objDesc.descriptorType <> typeObjectSpecifier THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 20416 , myErr );
- GOTO 9;
- END;
-
- { we've got an obj spec - let's resolve it }
- IF CatchErr( AEResolve(objDesc,kAEIDoMinimum,relObjToken) , 20417 , myErr ) THEN GOTO 9;
-
- { it better not be a list }
- IF relObjToken.descriptorType = typeAEList THEN
- BEGIN
- gTempBool := CatchErr( errAENeedSingleItem , 20418 , myErr );
- GOTO 9;
- END;
-
- END; { of object not null }
-
- 9:
- IF myErr <> noErr THEN
- BEGIN
- { you only want to dispose of relObjToken in the error case }
- gTempBool := CheckErr( AEDisposeDesc(relObjToken) , 20419 );
- position := kAEBefore; { just for neatness }
- END;
-
- gTempBool := CheckErr( DisposeSomeDescs(@objDesc,@newRec,NIL,NIL,NIL) , 20420 );
-
- DecodeInsertionLoc := myErr;
- END; { DecodeInsertionLoc }
-
- {$S QuillNew2}
- FUNCTION DecodeOrdinal(ordData: AEDesc; count: LongInt; VAR index: LongInt;
- VAR allFlag: BOOLEAN; VAR zeroFlag: BOOLEAN): OSErr;
- { this routine is used whenever an element is specified by an absolute position
- within a sequence of elements - such as "word 3 of window 'johnson'", "any line
- of item 17 of window 'Kelvin'", etc. The data specifying the position can be
- a positive integer (which just means the actual position of the element in the
- sequence: 1 for the first element, 2 for the second, etc.), a negative integer
- (which indicates position relative to the last element of the sequence: -1 is
- the last element, -2 the next to last, etc.), or a descriptor of typeAbsoluteOrdinal:
- kAEFirst, kAELast, kAEMiddle, kAEAny, or kAEAll.
-
- DecodeOrdinal takes the data specifying the position, and a count of all the elements
- in the sequence under consideration, and returns (whenever possible) a positive integer
- (in the return VAR index) representing the actual position of the element in the sequence
- (1 for first, 2 for second, etc.). It also returns flags indicating (a) whether the
- ordinal was kAEAll and (b) whether the count was 0; both of these are conditions that
- many calling routines will have to special-case. In the case of kAEAll, the return VAR
- index is set to the count; in the case of count = 0, the return VAR index is set to 0.
-
- There are a few error conditions: (a) count < 0; (b) bad ordData (not an integer, and
- not one of the five defined absolute ordinal specifiers). **CHECK - should "integer ordData
- out of range" (for example, an integer > count, or < -count, or = 0) be an error,
- or should we allow that so that people can talk about "the hypothetical element
- beyond the last", or whatever? For now, let's make that a non-error.
-
- INPUTS: ordData a descriptor that specifies an ordinal - either
- an integer (positive or negative) or something
- of typeAbsoluteOrdinal
- count the total number of elements in the group involved
- (number of windows, number or chars, or whatever)
- index return VAR for the actual position being described
- allFlag return VAR: TRUE if the ordData was kAEAll, FALSE o.w.
- zeroFlag return VAR: TRUE if the count was zero (for many
- calling routines this is an error condition), FALSE o.w.
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- absOrd: DescType;
- intOrd: LongInt;
- BEGIN
- myErr := genericErr;
- index := count;
- allFlag := FALSE;
-
- zeroFlag := (count = 0);
- IF count < 0 THEN
- BEGIN
- myErr := errAEBadData;
- GOTO 9;
- END;
-
- myErr := MyAECoerceDescPtr(ordData,typeAbsoluteOrdinal,@absOrd,SizeOf(absOrd),gActSize);
- IF myErr = noErr THEN
- BEGIN
- { got an absolute ordinal }
- { note that, as we enter here, index = count and myErr = noErr }
- allFlag := (absOrd = kAEAll);
- IF allFlag THEN GOTO 9; { finish up }
-
- IF (absOrd <> kAEFirst) & (absOrd <> kAELast) & (absOrd <> kAEMiddle) & (absOrd <> kAEAny) THEN
- BEGIN
- myErr := errAEBadData;
- GOTO 9;
- END;
-
- IF zeroFlag | (absOrd = kAELast) THEN GOTO 9; { in both cases, index = count (already done) }
-
- IF absOrd = kAEFirst THEN index := 1
- ELSE IF absOrd = kAEMiddle THEN index := (count + 1) DIV 2
- ELSE index := MyRandom(count);
-
- GOTO 9;
- END; { of absolute ordinal }
-
- { try actual integer }
- IF CatchErr( MyAECoerceDescPtr(ordData,typeLongInteger,@intOrd,SizeOf(intOrd),gActSize) ,
- 19813 , myErr ) THEN GOTO 9;
-
- IF intOrd < 0 THEN index := count + intOrd + 1 { e.g., intOrd = -1 means index = count }
- ELSE index := intOrd;
-
- { should we validate index here (wrt count)? let's skip it for now }
-
- 9: { finish up }
- DecodeOrdinal := myErr;
- END; { DecodeOrdinal }
-
- {$S QuillNew2}
- PROCEDURE DeleteThisText(myText: TextToken);
- { delete the text represented by myText. In the case
- of lines or items, we delete a delimiter (CR or comma,
- respectively) along with it - otherwise we would still
- have a (0-length) line or item.
- INPUTS: myText token for the text to be deleted
- OUTPUTS: none
- NOTES: for words, HyperCard will swallow an adjacent space
- (just one), but not adjacent CRs - should we do it
- that way?
- }
- BEGIN
- { note that myText is not VAR; we're dealing with a local copy }
- WITH myText DO
- BEGIN
- IF tokenClass = cSpot THEN EXIT(DeleteThisText); { nothing to do }
-
- IF (tokenClass = cItem) | (tokenClass = cLine) THEN ExtendTextElem(myText);
-
- IF tokenClass = cWord THEN ExtendWord(myText);
-
- { ready to delete now }
- SelectTextToken(myText);
- TEDelete(DocumentPeek(tokenWndw)^.docTE);
- DirtyWindow(tokenWndw);
- END;
-
- END; { DeleteThisText }
-
- {$S QuillNew2}
- FUNCTION DeleteThisObj(myObj: AEDesc): OSErr;
- { coerce the given obj into something that can be deleted -
- a window, piece of text, or list thereof - and delete it.
- Since the list may contain embedded lists, the routine is
- potentially recursive.
- INPUTS: myObj the obj to be deleted
- OUTPUTS: error code (noErr if none)
- NOTES: if myObj is a list, we assume it's been given to us from
- the OSL, and is properly ordered so that, if we delete
- from the end of the list on up, we get no side effects
- }
- LABEL 9;
- VAR myErr: OSErr;
- tempDesc: AEDesc;
- delObj: AEDesc;
- itemCount: LongInt;
- i: LongInt;
- thisItem: AEDesc;
- window: WindowPtr;
- myText: TextToken;
- BEGIN
- myErr := genericErr;
- tempDesc := gNullDesc;
-
- { if it's an obj spec, we resolve it - because we don't want to coerce it to a list }
- { **CHECK - note clever new use of assignments - it's subtle, be careful! - BHM 9/3/91 }
- { it avoids an unnecessary duplication }
-
- { delObj gets neither initialized nor disposed of; it's only another name for some }
- { other descriptor (either myObj or tempObj, depending) }
-
- delObj := myObj;
- IF delObj.descriptorType = typeObjectSpecifier THEN
- BEGIN
- IF CatchErr( AEResolve(myObj,kAEIDoMinimum,tempDesc) , 21613 , myErr )
- THEN GOTO 9;
- delObj := tempDesc;
- END;
-
-
- IF delObj.descriptorType = typeAEList THEN
- BEGIN
- { count the items }
- IF CatchErr( AECountItems(delObj,itemCount) , 21614 , myErr ) THEN GOTO 9;
-
- { work backwards through the list, calling yourself recursively }
- FOR i := itemCount DOWNTO 1 DO
- BEGIN
- { get the item }
- IF CatchErr( AEGetNthDesc(delObj,i,typeWildCard,gReturnedKeywd,thisItem) , 21615 ,
- myErr ) THEN GOTO 9;
-
- { delete it }
- IF CatchErr( DeleteThisObj(thisItem) , 21616 , myErr ) THEN GOTO 9;
-
- { dispose of the item }
- gTempBool := CheckErr( AEDisposeDesc(thisItem) , 21617 );
- thisItem := gNullDesc; { just for neatness }
- END; { of FOR loop }
- GOTO 9;
- END; { of list }
-
- { not a list - get something we can delete }
- IF MyAECoerceDescPtr(delObj,typeMyWndw,@window,SizeOf(window),gActSize) = noErr THEN
- BEGIN
- { it's a window }
- ShutTheWindow(window);
- myErr := noErr;
- GOTO 9;
- END;
-
- IF MyAECoerceDescPtr(delObj,typeMyText,@myText,SizeOf(myText),gActSize) = noErr THEN
- BEGIN
- { it's text }
- DeleteThisText(myText);
- myErr := noErr;
- GOTO 9;
- END;
-
- { it's nothing we can delete }
- myErr := errAEEventNotHandled; { or whatever }
-
- 9: { finish up }
-
- gTempBool := CheckErr( AEDisposeDesc(tempDesc) , 21618 ); { but NOT delObj! }
-
- DeleteThisObj := myErr;
- END; { DeleteThisObj }
-
-
- {$S QuillNew2}
- PROCEDURE DestroyKeyBuffer;
- { this routine throws away the storage associated
- with the key buffer
- INPUTS: none
- OUTPUTS: none
- 10/03/91 BHM Added bufDesc
- }
- BEGIN
- DisposHandle(Handle(keyBuffer.bufChars));
- gTempBool := CheckErr( AEDisposeDesc(keyBuffer.bufDesc) , 22113 );
- END; { DestroyKeyBuffer }
-
-
- {$S QuillNew }
- PROCEDURE DirtyWindow(window: WindowPtr);
- { mark the given window as dirty
- INPUTS: window ptr to the window
- OUTPUTS: none
- }
- BEGIN
- DocumentPeek(window)^.dirtyFlag := TRUE;
- END; { DirtyWindow }
-
- {$S QuillNew }
- FUNCTION DisposeSomeDescs(desc1Ptr, desc2Ptr, desc3Ptr, desc4Ptr, desc5Ptr: DescPtr): OSErr;
- { dispose of a bunch of descriptors. The inputs are pointers to the descriptors.
- If one or more of the pointers is NIL, then the routine ignores all the inputs
- after that one (they should be NIL, too). So, for example, if desc3Ptr is NIL,
- only the descriptors pointed to by desc1Ptr and desc2Ptr are disposed of.
- INPUTS: as above
- OUTPUTS: error code (noErr if none). If any of the AEDisposeDesc calls returns
- an error, DisposeSomeDesc will return the first such error generated;
- but it will continue to (try to) dispose of all the input descriptors.
- NOTES: (1) as currently spec'ed, AEDisposeDesc never returns an error (just
- noErr); and for valid descriptors, it's hard to imagine what kind
- of error it would return. So all the error details here may be
- utterly pointless. Better safe than sorry, I always say.
- (2) **WARNING** if any of the inputs is NIL, it and all the subsequent
- inputs are ignored
- (3) **ANOTHER WARNING** this routine can be used to dispose of both
- local AEDesc's (local to the caller) and/or AEDesc's the caller
- is creating & returning for some higher routine to use (such desc's
- generally show up as VAR inputs in the calling routine). You ONLY
- dispose of these VAR input desc's to clean up when your routine
- generates an error. Thus many routines that call DisposeSomeDescs
- will contain two calls to it, one to be used when the call succeeds
- (to get rid of any local desc's that may have been created) and one
- to be used when the call fails (to get rid of both local and return
- desc's that may have been created). If you intialize all desc's to
- the null desc at the start of your routine (using InitSomeDescs),
- you won't have to keep track of which ones you have already created
- when you hit an error. But you do have to distinguish between local
- desc's and return desc's.
- See routines that call InitSomeDescs and DisposeSomeDescs to see what
- I mean.
-
- }
- LABEL 9;
- VAR myErr: OSErr;
- tempErr: OSErr;
- BEGIN
- myErr := noErr;
- IF desc1Ptr = NIL THEN GOTO 9; { finish up }
- myErr := AEDisposeDesc(desc1Ptr^);
-
- IF desc2Ptr = NIL THEN GOTO 9;
- tempErr := AEDisposeDesc(desc2Ptr^);
- IF myErr = noErr THEN myErr := tempErr; { we want to keep the first real error }
-
- IF desc3Ptr = NIL THEN GOTO 9;
- tempErr := AEDisposeDesc(desc3Ptr^);
- IF myErr = noErr THEN myErr := tempErr;
-
- IF desc4Ptr = NIL THEN GOTO 9;
- tempErr := AEDisposeDesc(desc4Ptr^);
- IF myErr = noErr THEN myErr := tempErr;
-
- IF desc5Ptr = NIL THEN GOTO 9;
- tempErr := AEDisposeDesc(desc5Ptr^);
- IF myErr = noErr THEN myErr := tempErr;
-
- 9: { finish up }
- DisposeSomeDescs := myErr;
- END; { DisposeSomeDescs }
-
- {$S QuillNew }
- PROCEDURE DoDragWindow(theWindow: WindowPtr; startPt: Point; boundsRect: Rect);
- { this routine does the normal DragWindow, and then sends an AppleEvent to
- (re)set the window position to its new value, for recording purposes
- INPUTS: same as DragWindow
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- VAR newPos: Point;
- index: INTEGER;
- BEGIN
- DragWindow(theWindow,startPt,boundsRect);
- newPos := WindowPeek(theWindow)^.strucRgn^^.rgnBBox.topLeft; { we use the structure rect for that }
- index := IndexFromWndwPtr(theWindow);
- SendAESetWndwPos(index,newPos);
- END; { DoDragWindow }
-
- {$S QuillNew}
- PROCEDURE DoHighLevelEvent(event: EventRecord);
- BEGIN
- { gTempBool := CheckErr( AEProcessAppleEvent(event) , 1213 );}
- gTempLong := AEProcessAppleEvent(event);
- END; { DoHighLevelEvent }
-
- PROCEDURE DoItemErr(itemNum: INTEGER; theErr: OSErr; placeNum: INTEGER);
- { this is a routine to call when you get an error while dealing with
- some item in an AEList - an error you want to register, but not enough
- to make you want to abort whatever activity you're involved in (for
- example: in HandlePrintDocs, if one of the items in the direct-object
- list turns out to be something you can't print). As implemented here,
- it puts up a dialog giving the item number, the error number, and
- the place number (a unique number associated with the place in the
- code where the error was generated). In a real application, the actions
- you would take would depend on where the error occurred, what kind
- of error it was, etc.
- INPUTS: itemNum number of the item that occasioned the error
- theErr error code
- placeNum location of the error
- OUTPUTS: none
- NOTES:
- }
- VAR itemStr: Str255;
- BEGIN
- IF (NOT gShowAllErrs) & gInHandler THEN EXIT(DoItemErr); { **CHECK - experimental }
- itemStr := Concat('trouble with item# ',MyNumToStr(itemNum),
- ': err# ',MyNumToStr(theErr),' at ',MyNumToStr(placeNum));
- DoMyAlert(itemStr);
- END;
-
- {$S QuillNew }
- PROCEDURE DoMenuClose(window: WindowPtr);
- { close the given window. We check with the user on
- save/don't save options, then bundle up the Close as
- an AppleEvent and send it to ourself.
- INPUTS: window the window to be closed
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- VAR wndwTitle: Str255;
- saveFlag: BOOLEAN;
- docFileGood: BOOLEAN;
- fileParamFlag: BOOLEAN;
- fileSpec: FSSpec;
- BEGIN
- { first the DA window stuff - **CHECK on whether we really need this }
- IF IsDAWindow(window) THEN
- BEGIN
- CloseDeskAcc(WindowPeek( window )^.windowKind);
- EXIT(DoMenuClose);
- END;
-
- IF IsAppWindow(window) THEN
- BEGIN
-
- { if window dirty, then ask user about saving and, if necessary, to what file }
- IF WindowIsDirty(window) THEN
- BEGIN
- IF NOT AskBeforeClosing(window,saveFlag,docFileGood,fileSpec) THEN EXIT(DoMenuClose); { user cancelled out of AskBeforeClosing }
- END
- ELSE
- BEGIN
- saveFlag := FALSE;
- docFileGood := FALSE; { just for neatness }
- END;
-
- { time to send the Close event }
- { if we're not going to save, don't send the
- optional file parameter. Also, if we are
- going to save, but the file spec came from
- the window doc record (as opposed to user
- actions), then, for recording purposes, we
- STILL don't want to send along the file
- parameter }
- fileParamFlag := saveFlag & (NOT docFileGood);
-
- SendAEClose(window,saveFlag,fileParamFlag,fileSpec);
- END; { of app window case }
-
- { if we get to here, we're fine }
- END; { DoMenuClose }
-
- {$S QuillNew}
- PROCEDURE DoMenuEdit(window: WindowPtr; editCode: INTEGER);
- { used when Copy, Cut, or Paste is chosen from the edit
- menu. Concoct an object representing selection in the given
- window, and send an Apple Event to perform the given edit
- action on that object.
- INPUTS: window ptr to the window
- editCode defined constant for the edit action:
- iCopy, iCut, or iPaste
- OUTPUTS: none
- NOTES: (1) an easier way to do the menu command would be to
- send the event without parameters, which would then
- act on the current selection; but this records better
- (2) IMPORTANT: this routine is NOT used with Clear
- (which is not a Core AppleEvent; we use Set Data)
- or Select All (which may not even be an AppleEvent
- action; we'll see . . . .)
- }
- LABEL 9;
- VAR selText: AEDesc;
- eventID: DescType;
- myAppleEvent: AppleEvent;
- defReply: AppleEvent;
- BEGIN
- InitSomeDescs(@selText,@myAppleEvent,@defReply,NIL,NIL);
-
- { make an object representing the selected text }
- IF CheckErr( MakeSelTextObj(window,selText) , 17513 ) THEN GOTO 9;
-
- { get the event ID }
- CASE editCode OF
- iCopy: eventID := kAECopy;
- iCut: eventID := kAECut;
- iPaste: eventID := kAEPaste;
- END;
-
- { create event }
- IF CheckErr( AECreateAppleEvent(kAEMiscStandards,eventID,gSelfAddrDesc,kAutoGenerateReturnID,kAnyTransactionID,myAppleEvent) , 17514 )
- THEN GOTO 9;
-
- { add parameter }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyDirectObject,selText) , 17515 ) THEN GOTO 9;
-
- { send the event }
- gTempBool := CheckErr( AESend(myAppleEvent,defReply,kAENoReply+kAECanInteract,kAENormalPriority,kAEDefaultTimeOut,NIL,NIL) ,
- 17516 );
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@selText,@myAppleEvent,@defReply,NIL,NIL) , 17517 );
- END; { DoMenuEdit }
-
- {$S QuillNew}
- PROCEDURE DoMenuMathoms(menuItem: INTEGER);
- { implements the Mathoms menu, which for now just
- has the toggle-the-error-mode command
- INPUTS: menuItem item number from Mathoms menu
- OUTPUTS: none
- }
- LABEL 9;
- VAR newErrMode: DescType;
- propDataDesc: AEDesc;
- BEGIN
- propDataDesc := gNullDesc;
- IF menuItem = iShowAllErrs THEN
- BEGIN
- { send an AppleEvent to change the app's error mode }
-
- { create the data desc }
- IF gShowAllErrs THEN newErrMode := kShowFewErrs
- ELSE newErrMode := kShowAllErrs;
-
- IF CheckErr( AECreateDesc(typeEnumerated,@newErrMode,SizeOf(newErrMode),propDataDesc) ,
- 18514 ) THEN GOTO 9;
-
- { now send }
- SendAESetObjProp(gNullDesc,pErrMode,propDataDesc);
- END;
-
- 9: { finish up }
- gTempBool := CheckErr( AEDisposeDesc(propDataDesc) , 18516 );
- END; { DoMenuMathoms }
-
- {$S QuillNew}
- PROCEDURE DoMenuNew;
- { send a CreateElement event to make a new, frontmost window
- INPUTS: none
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- LABEL 9;
- VAR myAppleEvent: AEDesc;
- insertionLoc: AEDesc;
- newClass: DescType;
- defReply: AEDesc;
- BEGIN
- InitSomeDescs(@myAppleEvent,@insertionLoc,@defReply,NIL,NIL);
-
- { create the event }
- IF CheckErr( AECreateAppleEvent(kAECoreSuite,kAECreateElement,gSelfAddrDesc,kAutoGenerateReturnID,
- kAnyTransactionID,myAppleEvent) , 22813 ) THEN GOTO 9;
-
- { create insertion loc - "beginning of null container" }
- IF CheckErr( MakeInsertionLoc(gNullDesc,kAEBeginning,insertionLoc) , 22814 )
- THEN GOTO 9;
-
- { add insertion loc to event }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyAEInsertHere,insertionLoc) , 22815 )
- THEN GOTO 9;
-
- { add desired class }
- newClass := cDocument;
- IF CheckErr( AEPutParamPtr(myAppleEvent,keyAEObjectClass,typeType,@newClass,SizeOf(newClass)) ,
- 22816 ) THEN GOTO 9;
-
- { send the event }
- gTempBool := CheckErr( AESend(myAppleEvent,defReply,kAENoReply+kAECanInteract,kAENormalPriority,
- kAEDefaultTimeOut,NIL,NIL) , 22817 );
-
- 9:
- { not really necessary to dispose of the default reply - we didn't ask for one - }
- { but I'm neat }
- gTempBool := CheckErr( DisposeSomeDescs(@myAppleEvent,@insertionLoc,@defReply,NIL,NIL) , 22819 );
- END; { DoMenuNew }
-
- {$S QuillNew}
- PROCEDURE DoMenuOpen;
- { get a file from the user and open a new window for it (by sending yourself the
- AppleEvent)
- INPUTS: none
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- VAR myTypeList: SFTypeList;
- mySFReply: StandardFileReply;
- BEGIN
- myTypeList[0] := 'QUIL';
- StandardGetFile(NIL,1,myTypeList,mySFReply);
- IF NOT mySFReply.sfGood THEN EXIT(DoMenuOpen); { user cancelled }
- SendAEOpenDoc(mySFReply.sfFile);
- END; { DoMenuOpen }
-
- {$S QuillNew}
- PROCEDURE DoMenuPrint;
- { called when the user selects Print from the File menu. Package
- up the front window as an object, and ship it off to myself
- in an AppleEvent Print event.
- INPUTS: none
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- VAR wndwObjSpec: AEDesc;
- index: LongInt;
- BEGIN
- { create an object specifier for the front window }
- index := 1;
- IF CheckErr( MakeObjSpecFromIndex(cDocument,gNullDesc,index,wndwObjSpec) , 2013)
- THEN EXIT(DoMenuPrint);
-
- { now send the event }
- SendAEPrintDoc(wndwObjSpec,TRUE); { use print dialog }
-
- { dispose of obj spec }
- gTempBool := CheckErr( AEDisposeDesc(wndwObjSpec) , 2019 );
- END; { DoMenuPrint }
-
-
- {$S QuillNew}
- PROCEDURE DoMenuPrintFile;
- { get a file from the user and print it (by sending yourself the
- AppleEvent).
- INPUTS: none
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- VAR myTypeList: SFTypeList;
- mySFReply: StandardFileReply;
- fileDesc: AEDesc;
- BEGIN
- myTypeList[0] := 'QUIL';
- StandardGetFile(NIL,1,myTypeList,mySFReply);
- IF NOT mySFReply.sfGood THEN EXIT(DoMenuPrintFile); { user cancelled }
- { change it into a descriptor }
- IF CheckErr( AECreateDesc(typeFSS,@mySFReply.sfFile,SizeOf(mySFReply.sfFile),fileDesc) , 2113 )
- THEN EXIT(DoMenuPrintFile);
- { send it to yourself }
- SendAEPrintDoc(fileDesc,FALSE); { don't use print dialog }
- gTempBool := CheckErr( AEDisposeDesc(fileDesc) , 2114 );
- END; { DoMenuPrintFile }
-
- {$S QuillNew }
- PROCEDURE DoMenuQuit;
- { send a Quit event to myself with the "ask user" option
- INPUTS: none
- OUTPUTS: none
- SIDE EFFECTS:
- NOTES:
- }
- BEGIN
- SendAEQuit(kAEAsk);
- END; { DoMenuQuit }
-
- {$S QuillNew }
- PROCEDURE DoMenuQuitNow;
- { send a Quit event to myself with the "don't save" option
- INPUTS: none
- OUTPUTS: none
- SIDE EFFECTS:
- NOTES:
- }
- BEGIN
- SendAEQuit(kAENo);
- END; { DoMenuQuitNow }
-
-
- {$S QuillNew }
- PROCEDURE DoMenuSave(window: WindowPtr);
- { save the given window to a file. If the window
- doc record has a good file spec, use it; o.w.
- prompt the user for a file.
- INPUTS: window ptr to window to be saved
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- BEGIN
- WITH DocumentPeek(window)^ DO
- IF docFile.vRefNum = badVRefNum THEN DoMenuSaveAs(window) { must prompt user }
- ELSE SendAESave(window,TRUE,docFile);
- END; { DoMenuSave }
-
- {$S QuillNew }
- PROCEDURE DoMenuSaveAs(window: WindowPtr);
- { prompt the user for a file and save the window to
- it (by sending yourself a Save AppleEvent)
- INPUTS: window ptr to window to be saved
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- NOTES: this routine only returns info on whether the
- user cancelled or not; it doesn't say whether
- the file creation (if needed) or the save itself
- were successful. In a real application, these would
- be important.
- }
- VAR wndwTitle: Str255;
- fileSpec: FSSpec;
- BEGIN
- GetWTitle(window,wndwTitle); { to use as default in SF dialog }
- IF NOT AskForFile(wndwTitle,fileSpec) THEN EXIT(DoMenuSaveAs); { user cancelled }
- SendAESave(window,TRUE,fileSpec);
- END; { DoMenuSaveAs }
-
- {$S QuillNew}
- PROCEDURE DoMenuStyle(window: WindowPtr; menuItem: INTEGER);
- { this routine implements the actions of the style menu.
- INPUTS: window ptr to the window in question
- menuItem item number selected by user
- OUTPUTS: none
- NOTES: in some cases the action to take (or, at least,
- the parameter to send with the AppleEvent Set Data
- call) depends not only on the item selected, but
- on the current state of the selected text.
- }
- VAR onStyles: Style;
- offStyles: Style;
- myStyle: StyleItem;
- myMode: INTEGER;
- myTextInfo: TextStyle;
- BEGIN
- onStyles := [];
- offStyles := [];
-
- IF menuItem = iPlain THEN
- BEGIN
- offStyles := gAllStyles; { everything }
- END
- ELSE
- BEGIN
- { not Plain; if the chosen style item is uniform across the text, }
- { we must turn it OFF; otherwise ON }
-
- { so get the style item }
- CASE menuItem OF
- iBold: myStyle := bold;
- iItalic: myStyle := italic;
- iUnderline: myStyle := underline;
- iOutline: myStyle := outline;
- iShadow: myStyle := shadow;
- END; { CASE }
-
- { check uniformity }
- myMode := doFace;
- IF TEContinuousStyle(myMode,myTextInfo,DocumentPeek(window)^.docTE) THEN
- BEGIN
- { uniform in SOME style (or Plain) - possibly my style }
- IF myStyle IN myTextInfo.tsFace
- THEN offStyles := [myStyle] { myStyle uniform in text, must turn it OFF }
- ELSE onStyles := [myStyle] { not uniform in myStyle, turn it on }
- END
- ELSE
- { no uniformity in any style }
- BEGIN
- onStyles := [myStyle];
- END;
- END; { of not Plain }
-
- { I don't really need all those BEGIN/END's up there, but they make things clearer }
-
- { got both sets - so set the style }
- gTempBool := CheckErr( SetStyleForSelText(window,onStyles,offStyles) , 17013 );
- END; { DoMenuStyle }
-
-
- {$S QuillNew}
- PROCEDURE DoMyAlert(alertStr: Str255);
- { just put up an alert with the given string }
- BEGIN
- IF AEInteractWithUser(kNoTimeOut,NIL,NIL) <> noErr THEN EXIT(DoMyAlert); { **CHECK - will this cause trouble? }
- ParamText(alertStr, '', '', '');
- gTempLong := Alert(rUserAlert, NIL);
- END; { DoMyAlert }
-
- {$S QuillNew}
- PROCEDURE DoMyErr(theErr: OSErr; placeNum: INTEGER);
- { puts up an alert box with the error num and the placeNum
- this is a bottleneck subroutine for handling errors. As
- currently written, it puts up an alert box with the error num
- and the placeNum (marking the place in the code where the
- error occurred). However, you can change it to do anything
- you want: write the inputs to a file, jump into the debugger,
- etc. You can also write tailored versions for particular
- calling routines, particular errors, etc.
- INPUTS: theErr os err to be reported
- placeNum number to mark actual place of error in code; should be unique
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- NOTES: as written, this routine does return to the calling function
- }
- VAR myErrStr: Str255;
- BEGIN
- IF (NOT gShowAllErrs) & gInHandler THEN EXIT(DoMyErr); { **CHECK - EXPERIMENTAL }
- IF AEInteractWithUser(kNoTimeOut,NIL,NIL) <> noErr THEN EXIT(DoMyErr); { **CHECK - what should we do here? }
- myErrStr := Concat('Hey, boys & girls - error #',MyNumToStr(theErr),' at ',MyNumToStr(placeNum));
- ParamText(myErrStr, '', '', '');
- gTempLong := Alert(rUserError, NIL);
- END; { DoMyErr }
-
- {$S QuillNew2}
- FUNCTION ElemFromAnythingAccessor(wantClass: DescType; container: AEDesc;
- containerClass: DescType; form: DescType; selectionData: AEDesc;
- VAR value: AEDesc; theRefCon: LongInt): OSErr;
- { return an arbitrary element (or "item") from a list. "Element",
- here, does NOT refer to "text elements" (such as char, word, etc.) -
- and, for that matter, "item" does not refer to comma-separated text.
- Instead, we're talking about the first element in a list, the second,
- etc. The wantClass is cListElem.
-
- This routine overrides (for wantClass = cListElem) the AnythingFromListAccessor,
- enabling us to get particular elements out of lists. If we relied on
- AnythingFromListAccessor in this case, it would, as always, return a list -
- which is not what we're looking for here (unless the given element happens to
- BE a list . . . .)
-
- The value returned by this accessor may be of any type, depending on what's found
- in the list.
-
- 08/22/91 BHM Put in a coercion to list so that this can get the number of elements
- in anything (the OSL can hand back a single token, rather than a 1-element
- list of tokens; in that case, we want to return that element, no an error)
- }
- LABEL 9;
- VAR myErr: OSErr;
- myList: AEDesc;
- elemCount: LongInt;
- index: LongInt;
- allFlag: BOOLEAN;
- zeroFlag: BOOLEAN;
- BEGIN
- myErr := accessorErr;
- InitSomeDescs(@value,@myList,NIL,NIL,NIL);
-
- { coerce the container to a list }
- IF CatchErr( AECoerceDesc(container,typeAEList,myList) , 21113 , myErr ) THEN GOTO 9;
-
- { now on to the element - how is it specified? }
- IF form = formAbsolutePosition THEN
- BEGIN
- { count the elements }
- IF CatchErr( AECountItems(myList,elemCount) , 21115 , myErr ) THEN GOTO 9;
-
- { get the element index }
- IF CatchErr( DecodeOrdinal(selectionData,elemCount,index,allFlag,zeroFlag) , 21116 ,
- myErr ) THEN GOTO 9;
-
- { if it's all, just duplicate the list }
- IF allFlag THEN
- BEGIN
- gTempBool := CatchErr( AEDuplicateDesc(myList,value) , 21118 , myErr );
- GOTO 9;
- END;
-
- { no, it's some particular element - get it from the list }
- gTempBool := CatchErr( AEGetNthDesc(myList,index,typeWildCard,gReturnedKeywd,value) , 21119 , myErr );
-
- GOTO 9;
- END; { of formAbsolutePosition }
-
- { unsupported naming form }
- gTempBool := CatchErr( errAEWrongDataType , 21120 , myErr );
-
- 9: { finish up }
-
- { NOTE: in this routine, if you get an error, there's no need to throw away value - }
- { because, in every path, there's no way to get an error AFTER creating value. So }
- { if you've got an error, value's still null }
-
- gTempBool := CheckErr( AEDisposeDesc(myList) , 21121 );
-
- ElemFromAnythingAccessor := myErr;
- END; { ElemFromAnythingAccessor }
-
-
- {$S QuillNew}
- FUNCTION EqualFSSpecs(aFile, bFile: FSSpec): BOOLEAN;
- { compare two file specs to see if they're equal. Ignore case
- (but not diacriticals) on the names. Return TRUE if equal,
- FALSE o.w.
- INPUTS: aFile first file
- bFile second file
- OUTPUTS: TRUE if equal, FALSE if not
- ERRORS:
- SIDE EFFECTS:
- }
- BEGIN
- EqualFSSpecs := FALSE;
- WITH aFile DO
- BEGIN
- IF vRefNum <> bFile.vRefNum THEN EXIT(EqualFSSpecs);
- IF parID <> bFile.parID THEN EXIT(EqualFSSpecs);
- IF NOT EqualString(name,bFile.name,FALSE,TRUE) { ignore case but not diacriticals }
- THEN EXIT(EqualFSSpecs);
- END;
- EqualFSSpecs := TRUE;
- END; { EqualFSSpecs }
-
- {$S QuillNew2}
- PROCEDURE ExtendTextElem(VAR myText: TextToken);
- { given a text token that represents an item or line, extend
- the text by 1 additional character to include an adjacent
- delimiter (comma for items, CR for lines) - if there is one
- (there won't be if the line or item constitutes all the text
- in its window). This routine is used when deleting items or
- lines - we want to "swallow" 1 delimiter with the element.
- INPUTS: myText token for the text; also used to return extended text
- OUTPUTS: none
- NOTES: (1) ExtendTextElem does NOT check to see if myText is of
- the right class, or validate it in any way. Make sure
- before you call. The routine is ONLY for items and lines.
- (See ExtendWord for words.)
- (2) if there's no room to extend the text (within its window),
- it's left alone
- (3) if the text is extended, we change the tokenClass to cText,
- since the resulting text is no longer - strictly speaking -
- an item or line
- }
- BEGIN
- WITH myText DO
- BEGIN
- IF tokenOffset + tokenLength < DocumentPeek(tokenWndw)^.docTE^^.teLength THEN
- BEGIN
- { you can extend to the right }
- tokenLength := tokenLength + 1;
- tokenClass := cText;
- EXIT(ExtendTextElem);
- END;
-
- { if you get here, you couldn't extend to the right }
- IF tokenOffset > 0 THEN
- BEGIN
- { you can extend text to the left }
- tokenOffset := tokenOffset - 1;
- tokenLength := tokenLength + 1;
- tokenClass := cText;
- END;
-
- END; { of WITH myToken }
- END; { ExtendTextElem }
-
- {$S QuillNew2}
- PROCEDURE ExtendWord(VAR myText: TextToken);
- { given a text token that represents a word, extend the
- text by 1 character to the right or left to include 1
- space - if that's possible. If there aren't any spaces
- adjacent to the word (that is, if the word is bounded
- by CRs and/or the start of the window's text and/or the
- end of the window's text), we DON'T extend the text.
- This routine is used when deleting a word - we want to
- swallow 1 space with the word.
- INPUTS: myText text token representing the word; also
- used to return extended text
- OUTPUTS: none
- NOTES: (1) ExtendWord does not check to see if the text token
- is a word, or validate it in any way. Let the caller
- beware.
- (2) If we do extend the text, we change its class to cText -
- it's not really just a word anymore.
- }
- VAR textHndl: Handle;
- textLength: LongInt;
- endOffP1: LongInt;
- BEGIN
- WITH myText DO
- BEGIN
-
- WITH DocumentPeek(tokenWndw)^.docTE^^ DO
- BEGIN
- textHndl := hText;
- textLength := teLength;
- END;
- endOffP1 := tokenOffset + tokenLength; { offset to 1 byte beyond last char in word }
-
- IF endOffP1 < DocumentPeek(tokenWndw)^.docTE^^.teLength THEN
- BEGIN
- { there's room on the right - but is it a space? }
- IF Ptr(ORD(textHndl^) + endOffP1)^ = asciiSpace THEN
- BEGIN
- { yes }
- tokenLength := tokenLength + 1;
- tokenClass := cText;
- EXIT(ExtendWord);
- END;
- END; { of room on the right }
-
- { if we get here, we were unable to extend to the right }
- IF tokenOffset > 0 THEN
- BEGIN
- { there's room on the left - but is there a space? }
- IF Ptr(ORD(textHndl^) + tokenOffset - 1)^ = asciiSpace THEN
- BEGIN
- { yes }
- tokenOffset := tokenOffset - 1;
- tokenLength := tokenLength + 1;
- tokenClass := cText;
- END;
- END; { of room on the left }
-
- END; { of WITH myText }
-
- END; { ExtendWord }
-
-
- {$S QuillNew}
- FUNCTION FileToTERec(fileSpec: FSSpec; teHndl: TEHandle): OSErr;
- { open the file and read the text and style info in it into the given
- new-style TERec. The file is in the "handle-list" format (see
- WriteHandlesToFile and FillHandlesFromFile), specifically:
-
- number of data blocks = 6 (2 bytes)
- size of text block (4 bytes)
- text block (variable)
- size of style record block (4 bytes)
- style record block (variable)
- size of style table block (4 bytes)
- style table block (variable)
- size of line-height table block (4 bytes)
- line-height table block (variable)
- size of null-style block (4 bytes)
- null-style block (variable)
- size of null-scrap block (4 bytes)
- null-scrap block (variable)
-
- INPUTS: fileSpec FSSpec for file
- teHndl handle to new-style TERec
- OUTPUT: TRUE if successful, FALSE o.w.
- ERRORS:
- SIDE EFFECTS:
- NOTES: this version returns an OSErr instead of TRUE/FALSE;
- it will replace the old one soon
- }
- LABEL 8,9;
- VAR myErr: INTEGER;
- refNum: INTEGER;
- teListCount: INTEGER;
- teInfoList: ARRAY[1..6] OF Handle;
- i: INTEGER;
- thisHndl: Handle;
- xferCount: INTEGER;
- textHndl: Handle;
- styleHndl: TEStyleHandle;
-
- PROCEDURE TossHandles;
- { dispose of all honest handles in the list - this is why I initialized the list to NILs }
- VAR j: INTEGER;
- BEGIN
- FOR j := 1 TO teListCount DO IF teInfoList[j] <> NIL THEN DisposHandle(teInfoList[j]);
- END;
-
- BEGIN { FileToTERec }
- IF CatchErr( FSpOpenDF(fileSpec,0,refNum) , 613 , myErr ) THEN GOTO 9; { must set function value }
- IF CatchErr( SetFPos(refNum,fsFromStart,0) , 614 , myErr ) THEN GOTO 8; { must close file }
-
- teListCount := 6;
-
- { get 6 handles, each 1 byte long - there's virtually no }
- { chance of the calls failing, but we'll check anyway }
-
- FOR i := 1 TO teListCount DO teInfoList[i] := NIL; { safety first }
-
- FOR i := 1 to teListCount DO
- BEGIN
- thisHndl := NewHandle(1);
- IF CatchErr( MemError , 615 , myErr ) THEN
- BEGIN
- TossHandles;
- GOTO 8;
- END;
- teInfoList[i] := thisHndl;
- END;
-
- IF CatchErr( FillHandlesFromFile(teListCount,@teInfoList,refNum,xferCount) , 616 , myErr ) THEN
- BEGIN
- TossHandles;
- GOTO 8;
- END;
-
- { we've read all the data blocks in from the file }
-
- { transfer the text }
- textHndl := teInfoList[1];
- HLock(textHndl);
- TESetText(textHndl^,GetHandleSize(textHndl),teHndl);
- DisposHandle(textHndl);
-
- { now set the other handle fields in the style handle }
-
- styleHndl := TEStyleHandle(teInfoList[2]);
- WITH styleHndl^^ DO { just setting some fields so I don't need to lock it }
- BEGIN
- styleTab := STHandle(teInfoList[3]);
- lhTab := LHHandle(teInfoList[4]);
- nullStyle := NullSTHandle(teInfoList[5]);
- nullStyle^^.nullScrap := STScrpHandle(teInfoList[6]);
- END;
-
- { now set the style handle into the teRec }
- SetStylHandle(styleHndl,teHndl);
-
- { all done }
-
- 8: { close file }
- gTempBool := CatchErr( FSClose(refNum) , 617 , myErr );
-
- 9: { set function result }
- FileToTERec := myErr;
-
- END;{ FileToTERec }
-
- {$S QuillNew}
- FUNCTION FillHandlesFromFile(VAR listCount: INTEGER; listPtr: HandleListPtr;
- refNum: INTEGER; VAR xferCount: INTEGER): OSErr;
- { this routine reads data reads data from a file into handles in a list.
- The handles must already exist; the routine will resize them (this saves
- us some error-handling hassles about which handles need to be disposed).
- The file was presumably created by WriteHandlesToFile, and has the format
-
- number of data blocks in file INTEGER (2 bytes)
- size of 1st data block LongInt (4 bytes)
- first data block variable
- size of 2nd data block LongInt (4 bytes)
- 2nd data block variable
- etc.
-
- A "data block", here, is a variable-length stream of contiguous bytes in
- the file, meant to be read into a single handle,
-
- The list of handles is given by a count and a ptr to the list. The file
- must already be open, and is specified by a refNum. The routine does not
- close the file. It returns an error number, noErr if there was none. It
- also returns, in the VAR parameter listCount, the number of data blocks the
- file claimed to contain (i.e., the "number of data blocks" value in the file);
- and, in VAR parameter xferCount, the number of blocks that were successfully
- transferred. (If we can't even read the data block count, we'll return -1 in
- xferCount.)
-
- FillHandlesFromFile will NOT try to transfer more blocks than
- either the input listCount (because it would have no place to put them) or
- the "number of data blocks" value (because the file says there aren't that
- many in it).
-
- INPUTS: listCount number of handles in list; also return VAR for
- number of data blocks in file
- listPtr ptr to list of handles
- refNum refNum of the file
- xferCount return VAR for the number of data blocks transferred
- OUTPUTS: error number (noErr if everything is all right)
- ERRORS:
- SIDE EFFECTS:
- NOTES: all handles must enter this routine unlocked; they will be returned unlocked
- }
- LABEL 8;
- VAR sizeLength: LongInt;
- myErr: OSErr;
- blockCount: INTEGER;
- i: INTEGER;
- dataSize: LongInt;
- dataHndl: Handle;
- BEGIN
- { read the data block count }
- sizeLength := SizeOf(blockCount); { 2 bytes, but we need it in a var }
- IF CatchErr( FSRead(refNum,sizeLength,@blockCount) , 1413 , myErr ) THEN
- BEGIN
- xferCount := -1; { couldn't even read the data block count }
- FillHandlesFromFile := myErr;
- EXIT(FillHandlesFromFile);
- END;
-
- { if you get this far, myErr is already set to noErr }
-
- IF listCount > blockCount THEN listCount := blockCount; { that cuts it down to size }
- FOR i := 1 to listCount DO
- BEGIN
- { read the data block size }
- sizeLength := SizeOf(dataSize); { 4 bytes, we need it in a var }
- IF CatchErr( FSRead(refNum,sizeLength,@dataSize) , 1414 , myErr ) THEN
- BEGIN
- xferCount := i-1;
- GOTO 8; { leave loop on error }
- END;
-
- { size the handle }
- dataHndl := listPtr^[i];
- SetHandleSize(dataHndl,dataSize);
- IF CatchErr( MemError , 1415 , myErr ) THEN
- BEGIN
- xferCount := i-1;
- GOTO 8; { leave loop on error }
- END;
- { read the data block }
- HLock(dataHndl);
- myErr := FSRead(refNum,dataSize,dataHndl^);
- HUnlock(dataHndl); { before checking for error }
- { NOW check for error }
- IF CheckErr( myErr , 1416 ) THEN
- BEGIN
- xferCount := i-1;
- GOTO 8; { leave loop on error }
- END;
-
- END; { of FOR loop }
-
- { got through the loop okay }
- xferCount := listCount;
-
- 8:
- FillHandlesFromFile := myErr;
- END; { FillHandlesFromFile }
-
- {$S QuillNew}
- FUNCTION GetDataFromAppProp(appPropDesc: AEDesc; VAR propDataDesc: AEDesc): OSErr;
- { given a descriptor which represents a prop of the app - and which
- should be of, or coercible to, typeMyAppProp - return a descriptor
- containing the data corresponding to that property (using the
- property's "best" data type)
- INPUTS: appPropDesc a descriptor for a property of the app. Must
- be of, or coercible to, typeMyAppProp
- propDataDesc return VAR for the data for the prop
- OUTPUTS: error code (noErr if none)
- NOTES:
- 09/16/91 BHM formerly GetPropForApp
- 02/17/92 BHM added pUserSelection
- }
- LABEL 9;
- VAR myErr: OSErr;
- myAppProp: DescType;
- window: WindowPtr;
- myErrMode: DescType;
- BEGIN
- myErr := genericErr;
- propDataDesc := gNullDesc;
-
- { which prop? }
- IF CatchErr( MyAECoerceDescPtr(appPropDesc,typeMyAppProp,@myAppProp,
- SizeOf(myAppProp),gActSize) , 18413 , myErr ) THEN GOTO 9;
-
- IF myAppProp = pUserSelection THEN
- BEGIN
- window := FrontWindow;
- IF window = NIL THEN
- BEGIN
- gTempBool := CatchErr( errAENoUserSelection , 18414 , myErr );
- GOTO 9;
- END;
-
- { make obj spec for user selection }
- gTempBool := CatchErr( SmartMakeSelTextObj(window,propDataDesc) , 18415 , myErr );
- GOTO 9;
- END; { pUserSelection }
-
- IF myAppProp = pErrMode THEN
- BEGIN
- { get the current mode }
- IF gShowAllErrs THEN myErrMode := kShowAllErrs
- ELSE myErrMode := kShowFewErrs;
-
- { return descriptor for it }
- gTempBool := CatchErr( AECreateDesc(typeEnumerated,@myErrMode,SizeOf(myErrMode),propDataDesc) ,
- 18416 , myErr );
- GOTO 9;
- END; { pErrMode }
-
- { if we get to here, we don't know about the prop }
- gTempBool := CatchErr( errAEWrongDataType , 18417 , myErr );
-
- 9:
- { note - since the creation of propDataDesc is always the last thing you do before }
- { coming here (if you create it at all), there's no reason to dispose of it even }
- { in the error case }
-
- GetDataFromAppProp := myErr;
- END; { GetDataFromAppProp }
-
-
- {$S QuillNew }
- FUNCTION GetFileAndSaveWndw(window: WindowPtr; useFS: BOOLEAN; VAR fileSpec: FSSpec): OSErr;
- { save a window to a file if at all possible. If useFS is TRUE,
- use the given file spec; if useFS is FALSE, then get a file
- spec using MyMakeFSSForWndw (which first looks in the window
- doc record for a file spec, and, if that fails, concocts one
- out of the window title and default directory and path). The
- file spec you wind up using should be returned in fileSpec.
- (If the call fails, fileSpec should be marked as invalid by
- setting its vRefNum to badVRefNum.) Create the file if necessary.
- Don't interact with the user, and overwrite an existing file if
- you have to.
-
- Th-th-th-that's all, folks!
-
- INPUTS: window ptr to the window to be saved
- useFS if TRUE, use fileSpec as input to determine file to save to;
- if FALSE, only use fileSpec for return info
- fileSpec result VAR for file spec you wound up using; also, if useFS
- is TRUE, use fileSpec as the file to save to; ALSO, if the call
- fails, mark fileSpec as invalid (vRefNum = badVRefNum) for safety
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- NOTES: (1) this routine does not "mark" the file doc record with the result
- fileSpec
- (2) it does not tell you whether the file already existed or not.
- We may want a smarter version in the future.
- }
- LABEL 8,9;
- VAR myErr: OSErr;
- tempErr: OSErr;
- BEGIN
- myErr := noErr; { we'll set an error later if we have to }
-
- { should we use fileSpec or get one elsewhere? }
-
- IF NOT useFS THEN { get one elsewhere }
- IF CatchErr( MyMakeFSSForWndw(window,fileSpec) , 6713 , myErr ) THEN GOTO 8; { error exit - mark fileSpec as invalid }
-
- { now we have a file spec }
- { create the file; this will give us a dupFNErr if the file already exists, which is ok }
-
- tempErr := FSpCreate(fileSpec,'quil','QUIL',smSystemScript); { smSystemScript = system script }
-
- IF (tempErr <> noErr) & (tempErr <> dupFNErr) THEN
- BEGIN
- { unexpected error with file creation }
- gTempBool := CatchErr( tempErr , 6714 , myErr );
- GOTO 8;
- END;
-
- { NOTE: if you want to worry about telling the caller that the file already
- existed, or about overwriting an existing file, or about changing the
- existing file so it has the right type et al, this is the place to do
- it. For now, I'm not going to bother. }
-
- { got the file spec, file exists - so save already! }
- IF NOT CatchErr( TERecToFile(DocumentPeek(window)^.docTE,fileSpec) , 6715 , myErr ) THEN GOTO 9; { good exit }
-
- 8: { error exit - mark fileSpec as invalid }
- fileSpec.vRefNum := badVRefNum;
-
- 9: { set function value }
- IF myErr = noErr THEN CleanWindow(window);
- GetFileAndSaveWndw := myErr;
- END; { GetFileAndSaveWndw }
-
- {$S QuillNew }
- FUNCTION GetInteractMode(theAppleEvent: AppleEvent; VAR interMode: LongInt): OSErr;
- { return the interact mode level from the AppleEvent. It should be kAENeverInteract,
- kAECanInteract, or kAEAlwaysInteract. If the call fails, it's undefined.
- INPUTS: theAppleEvent AppleEvent to get the interact mode from
- interMode result VAR to return the mode in
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR returnedType: DescType;
- actSize: Size;
- myErr: OSErr;
- BEGIN
- interMode := 0;
- IF CatchErr( AEGetAttributePtr(theAppleEvent,keyInteractLevelAttr,typeLongInteger,returnedType,
- @interMode,SizeOf(interMode),actSize), 20213 , myErr) THEN GOTO 9; { must set function value }
-
- IF (interMode <> kAENeverInteract) & (interMode <> kAECanInteract) & (interMode <> kAEAlwaysInteract)
- THEN gTempBool := CatchErr( errAEUnknownSendMode , 20214 , myErr );
-
- 9: { set function value }
- GetInteractMode := myErr;
- END; { GetInteractMode }
-
- {$S QuillNew }
- FUNCTION GetObjSpecFields(theObjSpec: AEDesc; VAR theClass: DescType; VAR theCont: AEDesc;
- VAR theKeyForm: AEKeyword; VAR theKeyData: AEDesc): OSErr;
- { given a desc for an object specifier, break it down into its 4 constituent parts
- INPUTS: theObjSpec the object specifier descriptor; must be of typeObjectSpecifier
- theClass result VAR for desired class (a DescType)
- theCont result VAR for container, as a desc (can be of many types)
- theKeyForm result VAR for the key form (an AEKeyword? **CHECK)
- theKeyData result VAR for key data, as a desc (can be of any type)
- OUTPUTS: error code (noErr if none)
- SIDE EFFECTS: if the call returns noErr, the caller is rersponsible for disposing
- of theCont and theKeyData descriptors
- NOTES: this new version returns the class and the key form directly, instead of
- as descriptors
- }
- LABEL 9;
- VAR myErr: OSErr;
- myObjSpecRec: AEDesc;
- BEGIN
- myErr := genericErr;
-
- InitSomeDescs(@theCont,@theKeyData,@myObjSpecRec,NIL,NIL);
-
- { make sure it's of typeObjectSpecifier }
- IF theObjSpec.descriptorType <> typeObjectSpecifier THEN
- BEGIN
- myErr := errAEWrongDataType;
- DoMyErr(myErr,11013);
- GOTO 9; { must clean up and set function value }
- END;
-
- { coerce it to typeAERecord to get at the object fields }
- IF CatchErr( AECoerceDesc(theObjSpec,typeAERecord,myObjSpecRec) , 11014 , myErr )
- THEN GOTO 9;
-
- { get the 4 fields }
- IF CatchErr( AEGetKeyPtr(myObjSpecRec,keyAEDesiredClass,typeType,gTempType,@theClass,
- SizeOf(theClass),gTempLong) , 11015 , myErr ) THEN GOTO 9;
-
- IF CatchErr( AEGetKeyDesc(myObjSpecRec,keyAEContainer,typeWildCard,theCont) , 11016 ,
- myErr ) THEN GOTO 9;
-
- IF CatchErr( AEGetKeyPtr(myObjSpecRec,keyAEKeyForm,typeEnumerated,gTempType,@theKeyForm,
- SizeOf(theKeyForm),gTempLong) , 11017 , myErr ) THEN GOTO 9;
-
- IF CatchErr( AEGetKeyDesc(myObjSpecRec,keyAEKeyData,typeWildCard,theKeyData) , 11018 ,
- myErr ) THEN GOTO 9;
-
- { everything looks fine }
- myErr := noErr;
-
- 9: { finish up }
- IF myErr = noErr THEN gTempBool := CheckErr( AEDisposeDesc(myObjSpecRec) , 11019 )
- ELSE gTempBool := CheckErr( DisposeSomeDescs(@theCont,@theKeyData,@myObjSpecRec,NIL,NIL) , 11020 );
-
- GetObjSpecFields := myErr;
- END; { GetObjSpecFields }
-
- {$S QuillNew2}
- FUNCTION GetDataFromToken(myToken: AEDesc; reqTypesList: AEDesc;
- VAR dataDesc: AEDesc; VAR notToken: BOOLEAN): OSErr;
- { given one of my private tokens, return the data corresponding
- to it, using a requested data type. If reqType is typeWildCard,
- use the token's default type.
-
- Actually, we now accept a LIST of requested types; we work down
- the list and use the first type we can cast the data to. If we
- find typeWildCard, we use the token's default type; if we find typeBest,
- we use the token's "best" (i.e., "richest") type.
-
- We are basically assuming that there exists for each token a "best" type,
- which can, at the very least, be coerced into the token's default type -
- as well as any other types we consider legitimate for the token. If this
- assumption is broken, we may need to do some restructuring of the code.
-
- INPUTS: myToken the token
- reqTypesList prioritized list of requested types for the returned
- data. NOTE: a null desc or an empty list will be
- treated as typeWildCard.
- dataDesc return VAR for the data
- notToken return VAR: TRUE if myToken is not one of my
- private tokens, FALSE o.w. This is valid even
- if GetDataFromToken returns an error
- OUTPUTS: error code (noErr if none)
- NOTES: **CHECK - QUESTIONS:
- (1) should we only accept explicit tokens, or should we try to
- coerce? (For now, we'll only accept tokens)
- (2) what should notToken be if we get a token that we can't (currently)
- get data on? (notToken = FALSE in this case; it's still a token)
- (3) should we go directly to token records here, or settle for the
- descriptors? (right now, we're using the descriptors)
- (4) should reqType be handled here, or passed on down to the lower-level
- routines? (we'll do it here for now)
-
- Note that this is not intended for descriptors of typeObjectSpecifier,
- and that it does not handle lists. That's intentional.
-
- 01/24/92 BHM (1) All the "Get...Data" routines below (GetDataFromWndwProp,
- GetStylTextData, etc.) are now spec'ed to return "typeBest"
- data rather than default type - which, interestingly enough,
- didn't require any changes in those routines. There are changes
- to this routine, however, to get the coercion to requested
- type(s) right
- (2) Changed to accept list of requested types
- }
- LABEL 9;
- VAR myErr: OSErr;
- myType: DescType;
- bestType: DescType;
- defType: DescType;
- newDesc: AEDesc;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@dataDesc,@newDesc,NIL,NIL,NIL);
-
- myType := myToken.descriptorType;
-
- { let's get notToken taken care of right away }
- notToken := (myType <> typeMyWndw) & (myType <> typeMyDoc) & (myType <> typeMyText)
- & (myType <> typeMyWndwProp) & (myType <> typeMyTextProp) & (myType <> typeMyAppProp);
-
- IF myType = typeMyWndwProp THEN
- BEGIN
- gTempBool := CatchErr( GetDataFromWndwProp(myToken,newDesc) , 20513 , myErr );
- GOTO 9;
- END;
-
- IF myType = typeMyText THEN
- BEGIN
- gTempBool := CatchErr( GetStylTextData(myToken,newDesc) , 20514 , myErr );
- GOTO 9;
- END;
-
- IF myType = typeMyTextProp THEN
- BEGIN
- gTempBool := CatchErr( GetDataFromTextProp(myToken,newDesc) , 20515 , myErr );
- GOTO 9;
- END;
-
- IF myType = typeMyAppProp THEN
- BEGIN
- gTempBool := CatchErr( GetDataFromAppProp(myToken,newDesc) , 20516 , myErr );
- GOTO 9;
- END;
-
- { nothing we know how to get the data of }
- myErr := errAEWrongDataType; { or whatever }
-
- 9: { finish up }
-
- IF myErr = noErr THEN
- BEGIN
- myErr := GetWildTypes(myToken,bestType,defType);
- IF myErr = noErr THEN myErr := MatchToReqList(newDesc,reqTypesList,bestType,defType,dataDesc);
- END;
-
- gTempBool := CheckErr( AEDisposeDesc(newDesc) , 20517 );
-
- GetDataFromToken := myErr;
- END; { GetDataFromToken }
-
- {$S QuillNew2}
- FUNCTION GetDataFromTokenList(myList: AEDesc; reqTypesList: AEDesc;
- VAR dataList: AEDesc): OSErr;
- { this routine takes a "token list" and returns a corresponding
- "data list". The elements of the token list may themselves be
- lists or tokens, but the ultimate "node elements" have to be
- tokens (not raw data).
- INPUTS: myList the "token list"
- reqTypesList prioritized list of requested types (we'll
- try them one at a time until we get one that
- works - see GetDataFromToken). NOTE: null
- desc or empty list will be treated as typeWildCard
- dataList return VAR for data list
- OUTPUTS: error code (noErr if none)
- NOTES: 01/24/92 BHM now handles lists of requested types
- }
- LABEL 9;
- VAR myErr: OSErr;
- itemCount: LongInt;
- i: LongInt;
- thisItem: AEDesc;
- dataDesc: AEDesc;
- notToken: BOOLEAN;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@dataList,@thisItem,@dataDesc,NIL,NIL);
-
- { count the items }
- IF CatchErr( AECountItems(myList,itemCount) , 20613 , myErr ) THEN GOTO 9;
-
- { make the return list }
- IF CatchErr( AECreateList(NIL,0,FALSE,dataList) , 20614 , myErr ) THEN GOTO 9;
-
- IF itemCount = 0 THEN GOTO 9; { empty list }
-
- { loop through the items }
- FOR i := 1 TO itemCount DO
- BEGIN
- { get the item }
- IF CatchErr( AEGetNthDesc(myList,i,typeWildCard,gReturnedKeywd,thisItem) , 20615 ,
- myErr ) THEN GOTO 9;
-
- { if it's a list, call myself recursively }
- IF thisItem.descriptorType = typeAEList THEN
- BEGIN
- IF CatchErr( GetDataFromTokenList(thisItem,reqTypesList,dataDesc) , 20616 , myErr )
- THEN GOTO 9;
- END
- ELSE
- BEGIN
- { otherwise assume it's a token }
- IF CatchErr( GetDataFromToken(thisItem,reqTypesList,dataDesc,notToken) , 20617 , myErr )
- THEN GOTO 9;
- END;
-
- { add the data desc to the end of the list }
- IF CatchErr( AEPutDesc(dataList,0,dataDesc) , 20618 , myErr ) THEN GOTO 9;
-
- { dispose of this item and data desc }
- gTempBool := CheckErr( DisposeSomeDescs(@thisItem,@dataDesc,NIL,NIL,NIL) , 20621);
- InitSomeDescs(@thisItem,@dataDesc,NIL,NIL,NIL); { just for neatness }
- END; { of FOR loop }
-
- 9: { finish up }
-
- { only dispose of data list in error case - it may have been created before an error occurred }
- IF myErr <> noErr THEN gTempBool := CheckErr( AEDisposeDesc(dataList) , 20619 );
-
- gTempBool := CheckErr( DisposeSomeDescs(@thisItem,@dataDesc,NIL,NIL,NIL) , 20620 );
-
- GetDataFromTokenList := myErr;
- END; { GetDataFromTokenList }
-
-
- {$S QuillNew}
- FUNCTION GetDataFromTextProp(textPropDesc: AEDesc; VAR propDataDesc: AEDesc): OSErr;
- { given a descriptor which represents a prop of some text - and which
- should be, or be coercible to, typeMyTextProp - return a descriptor
- containing the data corresponding to that property (using the property's
- "best" data type).
- INPUTS: textPropDesc a descriptor for the property of the text.
- Must already be typeMyTextProp, or at least
- coercible to it.
- propDataDesc return VAR for the data for the prop
- OUTPUTS: error code (noErr if none)
- NOTES: (1) later it may be necessary to separate the part of this
- routine that gets the text prop token from the part that
- actually goes after the prop value (but maybe not)
- (2) currently I am returning fonts as descriptors of typeMyFont,
- which is just a short integer with a fancy type. This is not,
- properly speaking, the default data type (which is typeChar).
- This gets fixed up at HandleGetData, but really we need to
- divide the code up differently. See HandleGetData for more
- information.
-
- 09/16/91 BHM formerly GetPropForTextDesc
- 09/16/91 BHM fonts are now of typeChar, nothing else
- }
- LABEL 9;
- VAR myErr: OSErr;
- myTextProp: TextPropToken;
- myStyle: TextStyle;
- myLineHeight: INTEGER;
- myFontAscent: INTEGER;
- myProp: DescType;
- mySize: INTEGER;
- fontName: Str255;
- wndwTE: TEHandle;
- onStyles: Style;
- offStyles: Style;
- myOffset: LongInt;
- BEGIN
- myErr := genericErr; { or whatever }
- propDataDesc := gNullDesc;
-
- IF CatchErr( MyAECoerceDescPtr(textPropDesc,typeMyTextProp,@myTextProp,
- SizeOf(myTextProp),gActSize) , 16213 , myErr ) THEN GOTO 9;
-
-
- WITH myTextProp DO
- BEGIN
- TEGetStyle(tpText.tokenOffset,myStyle,myLineHeight,myFontAscent,
- DocumentPeek(tpText.tokenWndw)^.docTE);
- myProp := tpProp;
- END;
-
- IF myProp = pPointSize THEN
- BEGIN
- mySize := myStyle.tsSize;
- { **CHECK - how do I get the application font size? }
- IF mySize = 0 THEN mySize := 12; { this way for now . . . }
- gTempBool := CatchErr( AECreateDesc(typeShortInteger,@mySize,SizeOf(mySize),propDataDesc) ,
- 16214 , myErr );
- GOTO 9;
- END;
-
- IF myProp = pFont THEN
- BEGIN
- GetFontName(myStyle.tsFont,fontName);
- gTempBool := CatchErr( StrToTextDesc(fontName,propDataDesc) , 16217 , myErr );
- GOTO 9;
- END;
-
- IF myProp = pTextStyles THEN
- BEGIN
- onStyles := myStyle.tsFace;
- offStyles := gAllStyles - onStyles;
- gTempBool := CatchErr( StyleSetsToStyleDesc(onStyles,offStyles,propDataDesc,TRUE,TRUE) , 16220 , myErr );
- GOTO 9;
- END;
-
- IF myProp = pUniformStyles THEN
- BEGIN
- { first, select text }
- WITH myTextProp.tpText DO
- BEGIN
- wndwTE := DocumentPeek(tokenWndw)^.docTE;
- TESetSelect(tokenOffset,tokenOffset + tokenLength,wndwTE);
- END;
-
- { then, get uniform styles }
- IF CatchErr( MyGetUniformStyles(wndwTE,onStyles,offStyles) , 16215 , myErr ) THEN GOTO 9;
- gTempBool := CatchErr( StyleSetsToStyleDesc(onStyles,offStyles,propDataDesc,TRUE,TRUE) , 16216 , myErr );
- GOTO 9;
- END;
-
- IF myProp = pLength THEN
- BEGIN
- gTempBool := CatchErr( AECreateDesc(typeLongInteger,@myTextProp.tpText.tokenLength,SizeOf(myTextProp.tpText.tokenLength),
- propDataDesc) , 16218 , myErr );
- GOTO 9;
- END;
-
- IF myProp = pOffset THEN
- BEGIN
- myOffset := myTextProp.tpText.tokenOffset + 1; { **CHECK - do we want the "+1"? }
- gTempBool := CatchErr( AECreateDesc(typeLongInteger,@myOffset,SizeOf(myOffset),
- propDataDesc) , 16219 , myErr );
- GOTO 9;
- END;
-
-
- { not a property we can handle right now }
- myErr := errAEWrongDataType;
-
- 9: { finish up }
- GetDataFromTextProp := myErr;
- END; { GetDataFromTextProp }
-
- {$S QuillNew}
- FUNCTION GetDataFromWndwProp(wndwPropDesc: AEDesc; VAR propDataDesc: AEDesc): OSErr;
- { given a descriptor which represents a prop of a window - and which should
- already be of typeMyWndwProp - return a descriptor containing the data
- corresponding to that property (using the property's "best" type).
- INPUTS: wndwPropDesc a descriptor representing the a property of a
- window. Usually, when this routine is called,
- the desc is already of typeMyWndwProp. At the
- very least, it must be coercible to that type.
- propDataDesc return VAR for the data corresponding to the prop
- OUTPUTS: error code (noErr if none)
- NOTES: this routine actually just grabs the window prop token out of its
- descriptor and calls GetWindowProp
- 09/16/91 BHM formerly GetPropForWndwDesc
- }
- LABEL 9;
- VAR myErr: OSErr;
- myWndwProp: WndwPropToken;
- BEGIN
- myErr := genericErr; { or whatever }
- propDataDesc := gNullDesc;
-
- IF CatchErr( MyAECoerceDescPtr(wndwPropDesc,typeMyWndwProp,@myWndwProp,
- SizeOf(myWndwProp),gActSize) , 14913 , myErr ) THEN GOTO 9;
-
- WITH myWndwProp DO
- BEGIN
- IF CatchErr( GetWindowProp(wpWndw,wpProp,propDataDesc) , 14914 , myErr )
- THEN GOTO 9;
- END;
-
- 9: { finish up }
- GetDataFromWndwProp := myErr;
- END; { GetDataFromWndwProp }
-
- {$S QuillNew2}
- FUNCTION GetSingularData(srcDesc: AEDesc; reqType: DescType; VAR dataDesc: AEDesc): OSErr;
- { this routine takes a descriptor and returns it as data of a requested type.
- The input descriptor can either be raw data or an object specifier; if it's
- an object specifier, it can only resolve to a single token, not a list of
- tokens. (This is what's needed - right now, at least - for the Set Data event.)
- If the requested type is typeWildCard, we return either a duplicate of the input
- data (if it's raw data) or use the object's default data type (if it's an object).
- INPUTS: srcDesc original descriptor - can be either raw data or an object specifier
- (resolving to a single object)
- reqType requested type
- dataDesc return VAR for data to be returned
- OUTPUTS: error code (noErr if none)
- NOTES: DON'T give this a (private) token; it would probably return it as data.
- All it knows about are object specifiers and raw data.
- 01/24/92 BHM modified to use new GetDataFromToken, which takes a LIST of req types,
- rather than just one (this routine still only takes one, however, which
- we stuff into a 1-element list)
- }
- LABEL 9;
- VAR myErr: OSErr;
- newDesc: AEDesc;
- reqTypesList: AEDesc;
- notToken: BOOLEAN; { we ignore this }
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@dataDesc,@newDesc,@reqTypesList,NIL,NIL);
-
- IF srcDesc.descriptorType = typeObjectSpecifier THEN
- BEGIN
- IF CatchErr( AEResolve(srcDesc,kAEIDoMinimum,newDesc) , 21013 , myErr ) THEN GOTO 9;
-
- { stuff the req type into a 1-element list } { this isn't really necessary in the typeWildCard case . . . . }
- IF CatchErr( AECreateList(NIL,0,FALSE,reqTypesList) , 21017 , myErr ) THEN GOTO 9;
- IF CatchErr( AEPutPtr(reqTypesList,0,typeType,@reqType,SizeOf(reqType)) , 21018 , myErr )
- THEN GOTO 9;
-
- { the next step, in addition to getting data when possible, will reject lists }
- gTempBool := CatchErr( GetDataFromToken(newDesc,reqTypesList,dataDesc,notToken) , 21014 , myErr );
-
- GOTO 9;
- END;
-
- { if it gets here, it's raw data - is it even worth checking against my token types? }
- gTempBool := CatchErr( AECoerceDesc(srcDesc,reqType,dataDesc) , 21015 , myErr );
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@newDesc,@reqTypesList,NIL,NIL,NIL) , 21016 );
-
- GetSingularData := myErr;
- END; { GetSingularData }
-
- {$S QuillNew2}
- FUNCTION GetStyleItemFromConst(myConst: DescType; VAR stylItem: StyleItem;
- VAR plainFlag: BOOLEAN): BOOLEAN;
- { this routine takes a typeEnumerated value and checks to see if it's a
- style item constant (kAEBold, kAEUnderline, etc. - possibly kAEPlain).
- If it isn't, we return FALSE; if it is, we return the corresponding
- style item. If the value is kAEPlain, we return TRUE in the plainFlag
- (and stylItem is undefined); if it's some other style item constant,
- we return FALSE in the plainFlag
- INPUTS: myConst a typeEnumerated value
- stylItem return VAR for the corresponding style item. Undefined
- if myConst is kAEPlain or is not a style item const at all
- plainFlag return VAR - TRUE if myConst is kAEPlain, FALSE if myConst
- is some other style constant. Undefined if myConst is not
- a style item const at all.
- OUTPUTS: TRUE if myConst is a style item const (kAEBold, kAEUnderline, etc. -
- possibly kAEPlain), FALSE o.w.
- }
- VAR i: INTEGER;
- BEGIN
- IF myConst = kAEPlain THEN
- BEGIN
- plainFlag := TRUE;
- stylItem := bold; { just some arbitrary value, it's really undefined here }
- GetStyleItemFromConst := TRUE;
- EXIT(GetStyleItemFromConst);
- END;
-
- FOR i := 1 TO kNumOfStyles DO
- BEGIN
- IF theStyles[i].stylConst = myConst THEN
- BEGIN
- { found it in the list }
- stylItem := theStyles[i].stylItem;
- plainFlag := FALSE;
- GetStyleItemFromConst := TRUE;
- EXIT(GetStyleItemFromConst);
- END;
- END; { of loop }
-
- { if we get here, it's not a style item const or kAEPlain }
- stylItem := bold; { just some value, really undefined }
- plainFlag := FALSE; { ditto }
- GetStyleItemFromConst := FALSE;
- END; { GetStyleItemFromConst }
-
-
- {$S QuillNew }
- FUNCTION GetStylTextData(textDesc: AEDesc; VAR dataDesc: AEDesc): OSErr;
- { given a text descriptor - which should already be of typeMyText - return
- a descriptor containing the data (both characters and style info) of that
- text. The return desc should be of typeStyledText.
- INPUTS: textDesc descriptor for the text. Preferably, this should
- already be of typeMyText when the routine is called.
- At the very least, it MUST be coercible to that type.
- dataDesc return VAR for the text's data. It will be returned
- as typeStyledText.
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- myText: TextToken;
- BEGIN
- myErr := genericErr; { or whatever }
- dataDesc := gNullDesc;
-
- IF CatchErr( MyAECoerceDescPtr(textDesc,typeMyText,@myText,SizeOf(myText),gActSize) ,
- 14813 , myErr ) THEN GOTO 9; { finish up }
-
- { NOTE: probably MakeStyledTextDesc should be folded into this routine. But for now we have it }
-
- IF CatchErr( MakeStylTextDesc(myText,dataDesc) , 14814 , myErr ) THEN GOTO 9;
-
- 9: { finish up }
-
- GetStylTextData := myErr;
- END; { GetStylTextData }
-
- {$S QuillNew}
- FUNCTION GetTextFromDesc(srcDesc: AEDesc; VAR dstDesc: AEDesc): OSErr;
- { try a few different things to get the data from a descriptor
- into text form.
- INPUTS: srcDesc original data
- dstDesc return VAR for data in text form
- OUTPUTS: error code (noErr if none)
- NOTES: This is a hack, and will probably be replaced in
- the near future with coercers, accessors, et al.
- }
- LABEL 9;
- VAR myErr: OSErr;
- myText: TextToken;
- BEGIN
- myErr := genericErr;
- dstDesc := gNullDesc;
-
- { first, just try to coerce it }
- myErr := AECoerceDesc(srcDesc,typeChar,dstDesc);
- IF myErr = noErr THEN GOTO 9; { we're done }
-
- { next, try to pick it up as a typeMyText }
- myErr := MyAECoerceDescPtr(srcDesc,typeMyText,@myText,SizeOf(myText),gActSize);
- IF myErr = noErr THEN
- BEGIN
- { got a text token, make a desc for it }
- gTempBool := CatchErr( TextTokenToDesc(myText,dstDesc) , 15613 , myErr );
- GOTO 9;
- END;
-
- myErr := errAEWrongDataType;
-
- 9:
- GetTextFromDesc := myErr;
- END; { GetTextFromDesc }
-
-
- {$S QuillNew}
- FUNCTION GetTextElemFromText(srcText: TextToken; elemClass: DescType;
- elemIndex: LongInt; VAR elemText: TextToken): OSErr;
- { given a text token, this routine will pick out a particular
- char, word, line, or item in it, and return the result as
- a new text token.
- INPUTS: srcText token describing the original text
- elemClass desired class - cChar, cWord, cLine, or cItem
- elemIndex position of the element within the text; 1 for
- first word (or whatever), 2 for second, etc.
- elemText return VAR for token describing the particular element
- OUTPUTS: error code; noErr if element is found. The most common error is
- errAEIllegalIndex - either there weren't enough of that kind of
- element, or elemIndex < 1
- NOTES: (1) the tokenWndw field of the return elemText token will be the same
- as the tokenWndw of srcText (in the noErr case). The tokenOffset field
- is always from the start of the window, NOT the start of srcText
- (2) unfortunately we can't do a CASE statement on the elemClass with
- our current Pascal compiler
- 7/1/91 BHM Added "spots" to the classes
- }
- LABEL 9;
- VAR myErr: OSErr;
- wndwTextHndl: Handle;
- srcTextPtr: Ptr;
- srcTextLength: LongInt;
- delChar: SignedByte;
- elemOffset: LongInt;
- elemLength: LongInt;
- BEGIN
- myErr := errAEIllegalIndex;
- InitTextToken(elemText);
-
- WITH srcText DO
- BEGIN
- wndwTextHndl := DocumentPeek(tokenWndw)^.docTE^^.hText;
- HLock(wndwTextHndl);
- srcTextPtr := Ptr(ORD(wndwTextHndl^) + tokenOffset);
- srcTextLength := tokenLength;
- END;
-
- IF (elemClass = cLine) | (elemClass = cItem) THEN
- BEGIN
- IF elemClass = cLine THEN delChar := asciiCR
- ELSE delChar := asciiComma;
- myErr := MyGetTextElem(srcTextPtr,srcTextLength,delChar,elemIndex,elemOffset,elemLength);
- GOTO 9;
- END;
-
- IF elemClass = cWord THEN
- BEGIN
- myErr := MyGetWord(srcTextPtr,srcTextLength,elemIndex,elemOffset,elemLength);
- GOTO 9;
- END;
-
- IF elemClass = cChar THEN
- BEGIN
- IF (elemIndex < 1) | (elemIndex > srcTextLength) THEN myErr := errAEIllegalIndex
- ELSE
- BEGIN
- elemOffset := elemIndex - 1;
- elemLength := 1;
- myErr := noErr;
- END;
- GOTO 9;
- END;
-
- IF elemClass = cSpot THEN
- BEGIN
- IF (elemIndex < 1) | (elemIndex > srcTextLength + 1) THEN myErr := errAEIllegalIndex
- ELSE
- BEGIN
- elemOffset := elemIndex - 1;
- elemLength := 0;
- myErr := noErr;
- END;
- GOTO 9;
- END;
-
- { looks like char and spot cases can be easily combined - **CHECK }
-
- { unknown element class }
- myErr := errAEWrongDataType;
-
- 9: { finish up }
- HUnlock(wndwTextHndl);
-
- IF myErr = noErr THEN WITH elemText DO
- BEGIN
- tokenClass := elemClass;
- tokenWndw := srcText.tokenWndw;
- tokenOffset := srcText.tokenOffset + elemOffset; { to get proper offset within common window }
- tokenLength := elemLength;
- END;
-
- GetTextElemFromText := myErr;
- END; { GetTextElemFromText }
-
- {$S QuillNew2}
- FUNCTION GetWildTypes(myToken: AEDesc; VAR bestType: DescType;
- VAR defType: DescType): OSErr;
- { given a token (of one of my private token types), return the
- "best type" (which is up to Quill) and the default type (which
- should match the Registry) for data from that token.
- INPUTS: myToken the token
- bestType return VAR for "best type"
- defType return VAR for default type
- OUTPUTS: error code (noErr if none)
- NOTES: (1) if the token represents a property of something,
- we will have to (in most cases) "open it up" and look
- at the particular property to get the types
- (2) sure wish I could case off of DescTypes! Probably this
- is better done with a table (hashed or otherwise)
- (3) IMPORTANT: the pContents property of windows/docs
- is not included here because the accessor returns a text
- token, which is properly handled below - EXPERIMENTAL - **CHECK
- }
- LABEL 9;
- VAR myErr: OSErr;
- myType: DescType;
- myWndwProp: WndwPropToken;
- myProp: DescType;
- myTextProp: TextPropToken;
- myAppProp: DescType;
-
- PROCEDURE AssignWildTypes(forBest: DescType; forDef: DescType);
- { This routine stuffs values into bestType and defType, *and sets
- myErr to noErr*! (bestType, defType, and myErr are all variables
- in the parent routine GetWildTypes)
- INPUTS: forBest value for bestType
- forDef value for defType
- OUTPUTS: none
- NOTES: wholely owned by GetWildTypes
- }
- BEGIN
- bestType := forBest;
- defType := forDef;
- myErr := noErr;
- END; { AssignWildTypes }
-
- BEGIN { GetWildTypes }
- myErr := genericErr;
- bestType := typeWildCard; { never true }
- defType := typeWildCard; { never true }
-
- myType := myToken.descriptorType;
-
- IF (myType = typeMyWndw) | (myType = typeMyDoc) THEN
- BEGIN
- AssignWildTypes(typeObjectSpecifier,typeObjectSpecifier);
- GOTO 9;
- END;
-
- IF myType = typeMyText THEN
- BEGIN
- AssignWildTypes(typeStyledText,typeIntlText);
- GOTO 9;
- END;
-
- IF myType = typeMyWndwProp THEN
- BEGIN { typeMyWndwProp }
-
- { get the token }
- IF CatchErr( MyAECoerceDescPtr(myToken,typeMyWndwProp,@myWndwProp,
- SizeOf(myWndwProp),gActSize) , 23713 , myErr ) THEN GOTO 9;
- myProp := myWndwProp.wpProp;
-
- { case off the prop }
- IF myProp = pBounds THEN AssignWildTypes(typeQDRectangle,typeQDRectangle)
- ELSE IF myProp = pPosition THEN AssignWildTypes(typeQDPoint,typeQDPoint)
- ELSE IF myProp = pName THEN AssignWildTypes(typeChar,typeIntlText)
- { ELSE IF myProp = pContents THEN AssignWildTypes(typeStyledText,typeIntlText) } { this is where it would go, if it belonged here }
- ELSE myErr := errAEWrongDataType; { don't know about that prop }
- GOTO 9;
- END; { typeMyWndwProp }
-
- IF myType = typeMyTextProp THEN
- BEGIN
- { get the token }
- IF CatchErr( MyAECoerceDescPtr(myToken,typeMyTextProp,@myTextProp,
- SizeOf(myTextProp),gActSize) , 23714 , myErr ) THEN GOTO 9;
- myProp := myTextProp.tpProp;
-
- { case off the prop }
- IF myProp = pPointSize THEN AssignWildTypes(typeShortInteger,typeShortInteger)
- ELSE IF myProp = pFont THEN AssignWildTypes(typeChar,typeChar)
- ELSE IF (myProp = pTextStyles) | (myProp = pUniformStyles) THEN AssignWildTypes(typeTextStyles,typeTextStyles)
- ELSE IF (myProp = pLength) | (myProp = pOffset) THEN AssignWildTypes(typeLongInteger,typeLongInteger)
- ELSE myErr := errAEWrongDataType; { don't know about that prop }
- GOTO 9;
- END; { typeMyTextProp }
-
- IF myType = typeMyAppProp THEN
- BEGIN
- { get the prop }
- IF CatchErr( MyAECoerceDescPtr(myToken,typeMyAppProp,@myProp,SizeOf(myProp),gActSize),
- 23715 , myErr ) THEN GOTO 9;
-
- IF myProp = pErrMode THEN AssignWildTypes(typeEnumerated,typeEnumerated)
- ELSE IF myProp = pUserSelection THEN AssignWildTypes(typeStyledText,typeObjectSpecifier)
- ELSE myErr := errAEWrongDataType; { don't know about that prop }
- END; { typeMyAppProp }
-
- 9:
- GetWildTypes := myErr;
- END; { GetWildTypes }
-
- {$S QuillNew }
- FUNCTION GetWindowProp(window: WindowPtr; theProp: DescType;
- VAR dataDesc: AEDesc): OSErr;
- { given a window and a property, return the value of the property
- for that window in a descriptor, using the prop's default type
- INPUTS: window ptr to the window
- theProp the property
- propDataDesc return VAR for the property value
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- NOTES: 09/10/91 BHM Just cleaned it up a little
- 01/31/92 BHM Added pVisible, pIndex, pIsModal, pIsResizable,
- pHasTitleBar, pIsModified
- 02/17/92 BHM IMPORTANT: pContents does not appear here because
- the accessor returns a text token, which is handled
- by GetStylTextData. EXPERIMENTAL - **CHECK
- **CHECK - I can imagine situations where would would have to know the
- requested type down at this low level - but those situations do not
- apply to any window properties. (The situation is: the default type
- loses some information, and there are valid requested types that can't
- be reconstructed/coerced from the default type.)
- }
- LABEL 9;
- VAR myRect: Rect;
- myErr: OSErr;
- myPoint: Point;
- wndwTitle: Str255;
- myText: TextToken;
- myDesc: AEDesc;
- myIndex: LongInt;
- boolProp: BOOLEAN;
- myBool: BOOLEAN;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@dataDesc,@myDesc,NIL,NIL,NIL);
-
- IF theProp = pBounds THEN
- BEGIN
- myRect := WindowPeek(window)^.strucRgn^^.rgnBBox; { don't need to lock the handle just for getting the rect }
- gTempBool := CatchErr( AECreateDesc(typeQDRectangle,@myRect,SizeOf(myRect),dataDesc) ,
- 9713 , myErr );
- GOTO 9; { finish up }
- END;
-
- IF theProp = pPosition THEN
- BEGIN
- myPoint := WindowPeek(window)^.strucRgn^^.rgnBBox.topLeft;
- gTempBool := CatchErr( AECreateDesc(typeQDPoint,@myPoint,SizeOf(myPoint),dataDesc) ,
- 9714 , myErr );
- GOTO 9;
- END;
-
- IF theProp = pName THEN
- BEGIN
- GetWTitle(window,wndwTitle);
- gTempBool := CatchErr( StrToTextDesc(wndwTitle,dataDesc) , 9715 , myErr );
- GOTO 9;
- END; { IF pName }
-
- IF theProp = pIndex THEN
- BEGIN
- myIndex := IndexFromWndwPtr(window);
- gTempBool := CatchErr( AECreateDesc(typeLongInteger,@myIndex,SizeOf(myIndex),dataDesc) ,
- 9718 , myErr );
- GOTO 9;
- END;
-
- { let's group all the boolean properties together }
- boolProp := TRUE; { assume for now }
- IF theProp = pVisible THEN myBool := WindowPeek(window)^.visible { all my windows are visible, but I'll do it the hard way for illustration }
- ELSE IF theProp = pIsModal THEN myBool := FALSE { none of my windows are modal }
- ELSE IF theProp = pIsResizable THEN myBool := TRUE { all are resizeable }
- ELSE IF theProp = pHasTitleBar THEN myBool := TRUE { all have title bar }
- ELSE IF theProp = pIsModified THEN myBool := DocumentPeek(window)^.dirtyFlag
- ELSE boolProp := FALSE;
-
- IF boolProp THEN
- BEGIN
- gTempBool := CatchErr( AECreateDesc(typeBoolean,@myBool,SizeOf(myBool),dataDesc) ,
- 9717 , myErr );
- GOTO 9;
- END;
-
- { if we get to here, it's not a prop we know }
- myErr := errAECantHandleClass; { or whatever - **CHECK }
-
- 9:
- { note - never an error after creating dataDesc, so we don't have to dispose of it even in the error case }
- gTempBool := CheckErr( AEDisposeDesc(myDesc) , 9721 );
-
- GetWindowProp := myErr;
- END; { GetWindowProp }
-
- {$S QuillNew }
- FUNCTION GotRequiredParams(theAppleEvent: AppleEvent): OSErr;
- { checks the AppleEvent to see if we've gotten all the required
- parameters; returns noErr if yes, errAEParamMissed if no,
- or passes along some other error if one occurs
- INPUTS: theAppleEvent AppleEvent to be checked
- OUTPUTS: as described above
- ERRORS:
- SIDE EFFECTS:
- }
- VAR myErr: OSErr;
- returnedType: DescType;
- actSize: Size;
- BEGIN
- { look for the keyMissedKeywordAttr, just to see if it's there }
- myErr := AEGetAttributePtr(theAppleEvent,keyMissedKeywordAttr,typeWildCard,returnedType,NIL,0,actSize);
- IF myErr = errAEDescNotFound THEN GotRequiredParams := noErr { attribute not there means we got all req params }
- ELSE IF myErr = noErr THEN GotRequiredParams := errAEParamMissed { attribute there means missed at least one }
- ELSE GotRequiredParams := myErr; { some unexpected arror in looking for the attribute }
- END; { GotReqiredParams }
-
- {$S QuillNew2}
- FUNCTION GrowKeyBuffer: BOOLEAN;
- { tries to grow the key buffer by a set amount
- INPUTS: none
- OUTPUTS: TRUE if succeeds, FALSE o.w. (mem error)
- }
- BEGIN
- GrowKeyBuffer := FALSE;
- WITH keyBuffer DO
- BEGIN
- SetHandleSize(Handle(bufChars),bufSize + kBufGrowAmount);
- IF MemError <> noErr THEN EXIT(GrowKeyBuffer);
- bufSize := bufSize + kBufGrowAmount;
- END;
- GrowKeyBuffer := TRUE;
- END; { GrowKeyBuffer }
-
-
- {$S QuillNew}
- FUNCTION HandleClose(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr;
- { close the object or objects represented by the direct parameter.
- For "dirty" objects, an optional parameter determines whether the
- app should save them without interacting (kAEYes), not save them
- (kAENo), or ask the user on each one (kAEAsk). If kAEYes, there
- may also be an optional destination file parameter - but there can
- only be one of them (we don't permit a list), so you better be closing
- only one thing. If no destination file is specified, the application
- uses defaults.
- }
- LABEL 9;
- VAR myErr: OSErr;
- myDirObj: AEDesc;
- saveOpt: DescType;
- myFSSpec: FSSpec;
- gotFileParam: BOOLEAN;
- resDesc: AEDesc;
- BEGIN
- PreHandler;
- myErr := genericErr;
- InitSomeDescs(@myDirObj,@resDesc,NIL,NIL,NIL);
-
- { get the direct object }
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyDirectObject,typeObjectSpecifier,myDirObj) ,
- 5713 , myErr ) THEN GOTO 9;
-
- { get optional save param, if any }
- saveOpt := kAEAsk; { the default }
- myErr := AEGetParamPtr(theAppleEvent,keyAESaveOptions,typeEnumerated,gReturnedType,
- @saveOpt,SizeOf(saveOpt),gActSize);
- IF myErr = errAEDescNotFound THEN myErr := noErr { optional parameter not found - not an error }
- ELSE IF CheckErr( myErr , 5714 ) THEN GOTO 9;
-
- IF saveOpt = kAEYes THEN
- BEGIN
- { check for optional destination file parameter }
- myErr := AEGetParamPtr(theAppleEvent,keyAEDestination,typeFSS,gReturnedType,
- @myFSSpec,SizeOf(myFSSpec),gActSize);
- gotFileParam := (myErr = noErr);
- IF myErr = errAEDescNotFound THEN myErr := noErr
- ELSE IF CheckErr( myErr , 5715 ) THEN GOTO 9;
- END;
-
- { make sure we got all required params }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 5716 , myErr ) THEN GOTO 9;
-
- { resolve the direct object }
- IF CatchErr( AEResolve(myDirObj,kAEIDoMinimum,resDesc) , 5717 , myErr )
- THEN GOTO 9;
-
- { now close - we dispatch on list vs. token}
- IF resDesc.descriptorType = typeAEList
- THEN gTempBool := CatchErr( CloseTokenList(resDesc,saveOpt,gotFileParam,myFSSpec) , 5718 , myErr )
- ELSE gTempBool := CatchErr( CloseToken(resDesc,saveOpt,gotFileParam,myFSSpec) , 5719 , myErr );
-
- 9:
- gTempBool := CheckErr( DisposeSomeDescs(@myDirObj,@resDesc,NIL,NIL,NIL) , 5720 );
- HandleClose := myErr;
- PostHandler(reply,myErr);
- END; { HandleClose }
-
-
-
- {$S QuillNew}
- FUNCTION HandleCopy(theAppleEvent: AppleEvent; reply: AppleEvent; handlerRefCon: LongInt): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- window: WindowPtr;
- BEGIN
- PreHandler;
- IF CatchErr( SetUpEdit(theAppleEvent,window) , 17813 , myErr ) THEN GOTO 9;
-
- { got the selection, so cut; pass any errors to the client (**CHECK) }
- gTempBool := CatchErr( MyDoCopy(window) , 17814 , myErr );
-
- 9: { finish up }
- HandleCopy := myErr;
- PostHandler(reply,myErr);
- END; { HandleCopy }
-
- {$S QuillNew}
- FUNCTION HandleCountElements(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- myDirObj: AEDesc;
- myClass: DescType;
- myCount: LongInt;
- BEGIN
- PreHandler;
- myErr := errAEEventNotHandled;
- myDirObj := gNullDesc;
-
- { pick up direct object, which is the container in which things are to be counted }
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyDirectObject,typeWildCard,myDirObj) , 17913 ,
- myErr ) THEN GOTO 9;
-
- { now the class of objects to be counted }
- IF CatchErr( AEGetParamPtr(theAppleEvent,keyAEObjectClass,typeType,gReturnedType,@myClass,SizeOf(myClass),gActSize) ,
- 17914 , myErr ) THEN GOTO 9;
-
- { missing any parameters? }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 17915 , myErr ) THEN GOTO 9;
-
- { now count }
- IF CatchErr( RealCountProc(myClass,myDirObj,myCount) , 17916 , myErr ) THEN GOTO 9;
-
- { add result to reply }
- IF reply.descriptorType <> typeNull THEN
- gTempBool := CatchErr( AEPutParamPtr(reply,keyDirectObject,typeLongInteger,@myCount,SizeOf(myCount)) ,
- 17917 , myErr );
-
- 9: { finish up }
-
- gTempBool := CheckErr( AEDisposeDesc(myDirObj) , 17918 );
-
- HandleCountElements := myErr;
- PostHandler(reply,myErr);
- END; { HandleCountElements }
-
- {$S QuillNew}
- FUNCTION HandleCreateElement(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr;
- { make a new element, placed as specified by the insertion loc. Right now
- we only create new windows (or documents) within the null container; and
- we ignore any initial data or initial prop data suppled. This will get
- more sophisticated in the future.
-
- Based on the old HandleNewElement. This needs to be split up a little.
- }
- LABEL 9;
- VAR myErr: OSErr;
- newElemClass: DescType;
- insertionLoc: AEDesc;
- relObjToken: AEDesc;
- position: DescType;
- relWndw: WindowPtr;
- newWndw: WindowPtr;
- newPos: DescType;
- index: LongInt;
- wndwObjSpec: AEDesc;
- BEGIN
- PreHandler;
- myErr := genericErr;
- InitSomeDescs(@insertionLoc,@relObjToken,@wndwObjSpec,NIL,NIL);
-
- { pick up the class of the new element }
- IF CatchErr( AEGetParamPtr(theAppleEvent,keyAEObjectClass,typeType,gReturnedType,
- @newElemClass,SizeOf(newElemClass),gActSize) , 22913 , myErr ) THEN GOTO 9;
-
- { pick up the insertion loc }
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyAEInsertHere,typeInsertionLoc,insertionLoc) ,
- 22914 , myErr ) THEN GOTO 9;
-
- { check for missing required parameters }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 22915 , myErr ) THEN GOTO 9;
-
- { is it a class we can handle? }
- IF (newElemClass <> cWindow) & (newElemClass <> cDocument) THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 22916 , myErr );
- GOTO 9;
- END;
-
- { decode the insertion loc }
- IF CatchErr( DecodeInsertionLoc(insertionLoc,relObjToken,position) , 22917 , myErr )
- THEN GOTO 9;
-
- { two cases: beginning/end, or before/after/replace }
- IF (position = kAEBeginning) | (position = kAEEnd) THEN
- BEGIN
- { beginning or end - rel obj better be null desc }
- IF relObjToken.descriptorType <> typeNull THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 22918 , myErr );
- GOTO 9;
- END;
-
- { so - beginning or end of null container }
-
- { two cases - no windows yet, or 1 or more windows }
- relWndw := FrontWindow;
- IF relWndw = NIL THEN
- BEGIN
- { no windows yet; create one }
- gTempBool := CatchErr( MyNewWindow(newWndw) , 22919 , myErr );
- { **CHECK - actually, the entire kAEBeginning case can be folded in here, whether there are windows already or not }
- GOTO 9;
- END;
- { there's 1 or more windows - set up inputs for MySendWindow }
-
- { we've already set up relWndw as the front window - correct as necessary }
- IF position = kAEEnd THEN relWndw := BackWindow;
-
- { set up a position for MySendWindow }
- IF position = kAEBeginning THEN newPos := kAEBefore ELSE newPos := kAEAfter;
-
- { and fall into MySendWindow . . . }
- { that is: if we get here, then we're in the beginning/end case, 1 or more }
- { windows already exists, and we're set up for MySendWindow - after we get }
- { a new window }
- END { beginning/end case }
-
- ELSE { before/after/into case }
- BEGIN
- { get the "relative" window }
- IF CatchErr( MyAECoerceDescPtr(relObjToken,typeMyWndw,@relWndw,SizeOf(relWndw),gActSize) ,
- 22920 , myErr ) THEN GOTO 9;
-
- { set newPos }
- newPos := position;
-
- { and fall into MySendWindow . . . }
- { if we get here, we're set up for MySendWindow - after we get a new window }
- END; { before/after/into case }
-
- { so get a new window already! }
- IF CatchErr( MyNewWindow(newWndw) , 22921 , myErr ) THEN GOTO 9;
-
- { and move it to its rightful place }
- gTempBool := CatchErr( MySendWindow(newWndw,relWndw,newPos) , 22922 , myErr );
-
- 9:
- { there's a few cases for clean-up }
-
- IF (myErr = noErr) & (reply.descriptorType <> typeNull) THEN
- BEGIN
- { must return an obj spec for the new window }
- index := IndexFromWndwPtr(newWndw);
- gTempBool := CatchErr( MakeObjSpecFromIndex(newElemClass,gNullDesc,index,wndwObjSpec) , 22923 , myErr );
- IF myErr = noErr THEN
- gTempBool := CatchErr( AEPutParamDesc(reply,keyDirectObject,wndwObjSpec) , 22924 , myErr );
- END; { of attaching a reply if need be }
-
- gTempBool := CheckErr( DisposeSomeDescs(@insertionLoc,@relObjToken,@wndwObjSpec,NIL,NIL) , 22925 );
-
- HandleCreateElement := myErr;
- PostHandler(reply,myErr);
- END; { HandleCreateElement }
-
- {$S QuillNew}
- FUNCTION HandleCut(theAppleEvent: AppleEvent; reply: AppleEvent; handlerRefCon: LongInt): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- window: WindowPtr;
- BEGIN
- PreHandler;
- IF CatchErr( SetUpEdit(theAppleEvent,window) , 17113 , myErr ) THEN GOTO 9;
-
- { got the selection, so cut; pass any errors to the client (**CHECK) }
- gTempBool := CatchErr( MyDoCut(window) , 17114 , myErr );
-
- 9: { finish up }
- HandleCut := myErr;
- PostHandler(reply,myErr);
- END; { HandleCut }
-
- {$S QuillNew2}
- FUNCTION HandleDeleteElement(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- myDirObj: AEDesc;
- BEGIN
- PreHandler;
- myErr := errAEEventNotHandled;
- myDirObj := gNullDesc;
-
- { pick up direct object, which is the thing to be deleted }
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyDirectObject,typeWildCard,myDirObj) , 21513 , myErr )
- THEN GOTO 9;
-
- { missing any parameters? }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 21514 , myErr ) THEN GOTO 9;
-
- { now delete }
- myErr := DeleteThisObj(myDirObj);
-
- 9: { finish up }
- gTempBool := CheckErr( AEDisposeDesc(myDirObj) , 21515 );
-
- HandleDeleteElement := myErr;
- PostHandler(reply,myErr);
- END; { HandleDeleteElement }
-
- {$S QuillNew2}
- FUNCTION HandleDoObjectsExist(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- myDirObj: AEDesc;
- resDesc: AEDesc;
- myBool: BOOLEAN;
- BEGIN
- PreHandler;
- myErr := genericErr;
- InitSomeDescs(@myDirObj,@resDesc,NIL,NIL,NIL);
-
- { pick up the direct object }
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyDirectObject,typeObjectSpecifier,myDirObj) ,
- 24413 , myErr ) THEN GOTO 9;
-
- { see if you can resolve it }
- myBool := (AEResolve(myDirObj,kAEIDoMinimum,resDesc) = noErr);
-
- { if they want a reply - and they SHOULD - return the result }
- IF reply.descriptorType <> typeNull THEN
- gTempBool := CatchErr( AEPutParamPtr(reply,keyAEResult,typeBoolean,@myBool,SizeOf(myBool)) ,
- 24414 , myErr );
-
- { that was easy! }
-
- 9:
- gTempBool := CheckErr( DisposeSomeDescs(@myDirObj,@resDesc,NIL,NIL,NIL) , 24415 );
-
- HandleDoObjectsExist := myErr;
- PostHandler(reply,myErr);
- END; { HandleDoObjectsExist }
-
- {$S QuillNew}
- FUNCTION HandleGetData(theAppleEvent: AppleEvent; reply: AppleEvent; handlerRefCon: LongInt): OSErr;
- { 09/16/91 BHM rewritten to handle token lists better
- 01/24/92 BHM now accepts lists of requested types
- }
- LABEL 9;
- VAR myErr: OSErr;
- myDirObj: AEDesc;
- reqType: DescType;
- reqTypesList: AEDesc;
- newDesc: AEDesc;
- notToken: BOOLEAN; { really, we ignore this one }
- dataDesc: AEDesc;
- BEGIN
- PreHandler;
- myErr := errAEEventNotHandled;
- InitSomeDescs(@myDirObj,@dataDesc,@reqTypesList,NIL,NIL);
-
- { pick up the direct object }
-
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyDirectObject,typeWildCard,myDirObj) ,
- 14613 , myErr ) THEN GOTO 9; { finish up }
-
- { get a requested return type list, if any }
- myErr := AEGetParamPtr(theAppleEvent,keyAERequestedType,typeAEList,gReturnedType,
- @reqType,SizeOf(reqType),gActSize);
-
- { NOTE: all lower-level routines treat a reqTypesList of typeNull as though it }
- { were a 1-element list containing typeWildCard, so we don't have to hoke up }
- { a 1-element list here }
-
- IF myErr = errAEDescNotFound THEN myErr := noErr
- ELSE IF myErr <> noErr THEN
- BEGIN
- { unexpected problem while trying to get param }
- gTempBool := CheckErr( myErr , 14614 );
- GOTO 9;
- END;
-
- { check for required parameters }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 14615 , myErr ) THEN GOTO 9;
-
- { now, get the data }
-
- { I'll do this fairly explicitly }
- { the direct object has to be an object specifier }
- IF CatchErr( AEResolve(myDirObj,kAEIDoMinimum,newDesc) , 14620 , myErr ) THEN GOTO 9;
-
- { the resolved object is either a token or a "token list" }
- IF newDesc.descriptorType = typeAEList THEN
- BEGIN
- { it's a list }
- IF CatchErr( GetDataFromTokenList(newDesc,reqTypesList,dataDesc) , 14621 , myErr ) THEN GOTO 9;
- END
- ELSE
- BEGIN
- { it better be a token }
- IF CatchErr( GetDataFromToken(newDesc,reqTypesList,dataDesc,notToken) , 14622 , myErr ) THEN GOTO 9;
- END;
-
-
- { if they wanted a reply, attach it now }
- IF reply.descriptorType <> typeNull THEN { this means they want a reply - **CHECK }
- gTempBool := CatchErr( AEPutParamDesc(reply,keyDirectObject,dataDesc) , 14618 , myErr );
-
- 9: { finish up }
-
- gTempBool := CheckErr( DisposeSomeDescs(@myDirObj,@dataDesc,@reqTypesList,NIL,NIL) , 14619 );
- HandleGetData := myErr;
- PostHandler(reply,myErr);
- END; { HandleGetData }
-
- {$S QuillNew}
- FUNCTION HandleMove(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- myDirObj: AEDesc;
- insertionLoc: AEDesc;
- relObjToken: AEDesc;
- position: DescType;
- resDesc: AEDesc;
- BEGIN
- PreHandler;
- myErr := genericErr;
- InitSomeDescs(@myDirObj,@insertionLoc,@relObjToken,NIL,NIL);
-
- { pick up the direct object }
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyDirectObject,typeObjectSpecifier,myDirObj) ,
- 19013 , myErr ) THEN GOTO 9;
-
- { pick up insertion loc }
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyAEInsertHere,typeInsertionLoc,insertionLoc) ,
- 19014 , myErr ) THEN GOTO 9;
-
- { make sure we got all the required params }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 19015 , myErr ) THEN GOTO 9;
-
- { decode the insertion loc }
- IF CatchErr( DecodeInsertionLoc(insertionLoc,relObjToken,position) , 19016 , myErr )
- THEN GOTO 9;
-
- { resolve the direct object }
- IF CatchErr( AEResolve(myDirObj,kAEIDoMinimum,resDesc) , 19017 , myErr )
- THEN GOTO 9;
-
- { now move - we dispatch on list vs. token }
- IF resDesc.descriptorType = typeAEList
- THEN gTempBool := CatchErr( MoveTokenList(resDesc,relObjToken,position) , 19018 , myErr)
- ELSE gTempBool := CatchErr( MoveToken(resDesc,relObjToken,position) , 19019 , myErr );
-
- 9:
- gTempBool := CheckErr( DisposeSomeDescs(@myDirObj,@insertionLoc,@relObjToken,NIL,NIL) , 19020 );
- HandleMove := myErr;
- PostHandler(reply,myErr);
- END; { HandleMove }
-
- {$S QuillNew}
- FUNCTION HandleOpenApp(theAppleEvent: AppleEvent; reply: AppleEvent; handlerRefCon: LongInt): OSErr;
- { check the event for missing required parameters - the Open App Event should have no required
- parameters at all. If there are any, or if your call to check them failed, return an error;
- otherwise return noErr and call MyNewWindow to open an untitled document
- }
- LABEL 9;
- VAR myErr: OSErr;
- BEGIN
- PreHandler;
- myErr := errAEEventNotHandled;
-
- { check required params }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 20013 , myErr )
- THEN GOTO 9; { finish up }
-
- { open a new window }
- gTempBool := CatchErr( MyNewWindow(WindowPtr(gTempPtr)) , 20014 , myErr );
-
- 9: { finish up }
- HandleOpenApp := myErr;
- PostHandler(reply,myErr);
- END; { HandleOpenApp }
-
- {$S QuillNew}
- FUNCTION HandleOpenDocs(theAppleEvent: AppleEvent; reply: AppleEvent; handlerRefCon: LongInt): OSErr;
- { get the list of things to be opened, and open them
- NOTES: the official definition of the OpenDocs event says that
- it takes a list of alias records. I ask for them as FSSpec's
- instead; it's more convenient for me, and the AE Manager will
- do the coercion automatically
- }
- LABEL 9;
- VAR myErr: INTEGER;
- docList: AEDescList;
- returnedType: DescType;
- actSize: Size;
- itemCount: LongInt;
- i: INTEGER;
- myFSSpec: FSSpec;
- keywd: AEKeyWord;
- itemErr: INTEGER;
- BEGIN
- PreHandler;
- myErr := errAEEventNotHandled;
- docList := gNullDesc;
-
- { pick up the direct object, which is a list of things to be opened }
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,docList) , 913 , myErr )
- THEN GOTO 9; { finish up }
-
- { check for missing required parameters }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 914 , myErr ) THEN GOTO 9;
-
- { count the items in the list }
- IF CatchErr( AECountItems(docList,itemCount) , 916 , myErr ) THEN GOTO 9;
-
- { for each item, open the associated doc, if possible }
- FOR i := 1 to itemCount DO
- BEGIN
- { get the file }
- itemErr := AEGetNthPtr(docList,i,typeFSS,keywd,returnedType,@myFSSpec,SizeOf(myFSSpec),actSize);
- IF itemErr <> noErr THEN DoItemErr(i,itemErr,917) { couldn't get a file from this item - handle error and go on }
- ELSE
- BEGIN
- itemErr := MyOpenWindow(myFSSpec);
- IF itemErr <> noErr THEN DoItemErr(i,itemErr,918) { couldn't open the file for this item - handle and go on }
- END;
- END; { of FOR }
-
- { everything looks fine }
- myErr := noErr;
-
- 9: { finish up }
- gTempBool := CheckErr( AEDisposeDesc(docList) , 919 );
- HandleOpenDocs := myErr;
- PostHandler(reply,myErr);
- END; { HandleOpenDocs }
-
- {$S QuillNew}
- FUNCTION HandlePaste(theAppleEvent: AppleEvent; reply: AppleEvent; handlerRefCon: LongInt): OSErr;
- { **NOTE: this will have to be rewritten to handle more parameters, which Paste can have }
- LABEL 9;
- VAR myErr: OSErr;
- window: WindowPtr;
- BEGIN
- PreHandler;
- IF CatchErr( SetUpEdit(theAppleEvent,window) , 18013 , myErr ) THEN GOTO 9;
-
- { got the selection, so paste; pass any errors to the client (**CHECK) }
- gTempBool := CatchErr( MyDoPaste(window) , 18014 , myErr );
-
- 9: { finish up }
- HandlePaste := myErr;
- PostHandler(reply,myErr);
- END; { HandlePaste }
-
- {$S QuillNew}
- FUNCTION HandlePrint(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr;
- { the direct parameter can be either an object specifier (which can
- resolve to a single token or a list of tokens) or a list of files.
- (If it's a single file, it will be coerced here to a 1-element list
- for convenience of handling).
-
- Here's the story on interaction: we look at the interaction mode of the event's
- SendMode. If it's kAECanInteract (which is what the Finder sends) or kAENeverInteract,
- we don't use the Print Dialog. If it's kAEAlwaysInteract (which is what Quill
- sends when the Print menu item is selected) we will try to bring up the Print
- Dialog, and fail if we can't (user interaction fails). In the kAEAlwaysInteract
- case, even if we have a list of object tokens, we'll only bring up the Print
- Dialog ONCE, and only when we actually have something to print.
-
- In order to do that, we use two globals (of all things!), gInterMode and
- gTriedDialog. They are initialized here.
- }
- LABEL 9;
- VAR myErr: OSErr;
- dirObj: AEDesc;
- resDesc: AEDesc;
- BEGIN
- PreHandler;
- myErr := genericErr;
- InitSomeDescs(@dirObj,@resDesc,NIL,NIL,NIL);
-
- { try to get the direct object as an obj spec }
- myErr := AEGetParamDesc(theAppleEvent,keyDirectObject,typeObjectSpecifier,dirObj);
-
- IF myErr <> noErr THEN
- BEGIN
- { failing that, a list - presumably of files }
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyDirectObject,typeAEList,dirObj) , 1713 ,
- myErr ) THEN GOTO 9;
- END;
-
- { check for missing params }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 1714 , myErr ) THEN GOTO 9;
-
- { get the interact mode form the event }
- IF CatchErr( GetInteractMode(theAppleEvent,gInterMode) , 1715 , myErr ) THEN GOTO 9;
- gTriedDialog := FALSE; { haven't tried it so far }
-
- { if it's an object, resolve it }
- IF dirObj.descriptorType = typeObjectSpecifier THEN
- BEGIN
- IF CatchErr( AEResolve(dirObj,kAEIDoMinimum,resDesc) , 1716 , myErr )
- THEN GOTO 9;
-
- { it's either a single token or a list thereof }
- IF resDesc.descriptorType = typeAEList
- THEN gTempBool := CatchErr( PrintTokenList(resDesc) , 1717 , myErr )
- ELSE gTempBool := CatchErr( PrintToken(resDesc) , 1718 , myErr );
-
- GOTO 9;
- END; { of typeObjectSpecifier }
-
- { if it gets here it's a list, presumably of files }
- gTempBool := CatchErr( PrintFileList(dirObj) , 1719 , myErr );
-
- 9:
- gTempBool := CheckErr( DisposeSomeDescs(@dirObj,@resDesc,NIL,NIL,NIL) , 1720 );
-
- HandlePrint := myErr;
- PostHandler(reply,myErr);
- END; { HandlePrint }
-
- {$S QuillNew }
- FUNCTION HandleQuitApp(theAppleEvent: AppleEvent; reply: AppleEvent; handlerRefCon: LongInt): OSErr;
- { quit the program. Pick up the interact mode and optional save parameter, for use by
- Terminate. The save parameter can be "yes" (save all documents without asking the user),
- "no" (don't save any documents), or "ask user" (ask on each document - the default in this
- case).
- NOTES: **CHECK on how I should let the client know that the user cancelled, a save
- failed, or whatever
- }
- LABEL 9;
- VAR myErr: OSErr;
- returnedType: DescType;
- saveOpt: DescType;
- tempErr: OSErr;
- actSize: Size;
- userCancelled: BOOLEAN;
- BEGIN
- PreHandler;
- myErr := errAEEventNotHandled;
-
- { pick up optional save parameter }
- saveOpt := kAEAsk; { the default }
-
- tempErr := AEGetParamPtr(theAppleEvent,keyAESaveOptions,typeEnumerated,returnedType,
- @saveOpt,SizeOf(saveOpt),actSize);
-
- IF (tempErr <> noErr) & (tempErr <> errAEDescNotFound) THEN
- BEGIN
- { some unexpected error while trying to get param }
- gTempBool := CatchErr( tempErr , 8215 , myErr );
- GOTO 9; { finish up }
- END;
-
- IF CatchErr( GotRequiredParams(theAppleEvent) , 8213 , myErr ) THEN GOTO 9;
-
- gTempBool := CatchErr( MyTerminate(saveOpt,userCancelled) , 8214 , myErr);
-
- 9: { set function value }
- HandleQuitApp := myErr;
- PostHandler(reply,myErr);
- END; { HandleQuitApp }
-
- {$S QuillNew }
- FUNCTION HandleSave(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr;
- { pick up the direct parameter as a thing that can be saved, and
- save it. There may be an optional parameter specifying a file to
- save to; if there isn't, come up with the best file you can
- (we'll use GetFileAndSaveWndw for that).
- If the call succeeds, it also changes the name of the window
- to the name of the file, and marks the window doc with the
- file spec. These may both be redundant for a "save" command
- (but possibly not for a "save as")
- The routine doesn't interact with the user; that's done
- "up top" (before the AppleEvent is sent)
- }
- LABEL 9;
- VAR returnedType: DescType;
- window: WindowPtr;
- actSize: Size;
- myErr: OSErr;
- tempErr: OSErr;
- gotFileParam: BOOLEAN;
- myFSSpec: FSSpec;
- BEGIN
- PreHandler;
- myErr := errAEEventNotHandled;
-
- { pick up the direct object as a window, the only thing I know how to save right now }
- IF CatchErr( AEGetParamPtr(theAppleEvent,keyDirectObject,typeMyWndw,returnedType,
- @window,SizeOf(window),actSize) , 7213 , myErr ) THEN GOTO 9; { finish up }
-
- { pick up optional file param, if any }
- tempErr := AEGetParamPtr(theAppleEvent,keyAEDestination,typeFSS,returnedType,
- @myFSSpec,SizeOf(myFSSpec),actSize);
-
- IF (tempErr <> noErr) & (tempErr <> errAEDescNotFound) THEN
- BEGIN
- { unexpected error while trying to get optional param }
- gTempBool := CatchErr( tempErr , 7214 , myErr );
- GOTO 9;
- END;
-
- gotFileParam := (tempErr = noErr);
-
- { check to make sure we got all required parameters }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 7215 , myErr ) THEN GOTO 9;
-
- { now save }
- gTempBool := CatchErr( GetFileAndSaveWndw(window,gotFileParam,myFSSpec) , 7216 , myErr );
-
- { and set window title and docFile }
- SetWTitle(window,myFSSpec.name);
- DocumentPeek(window)^.docFile := myFSSpec;
-
- 9: { set function result }
- HandleSave := myErr;
- PostHandler(reply,myErr);
- END; { HandleSave }
-
- {$S QuillNew}
- FUNCTION HandleSetData(theAppleEvent: AppleEvent; reply: AppleEvent; handlerRefCon: LongInt): OSErr;
- { 09/17/91 BHM rewritten to handle lists better
- }
- LABEL 9;
- VAR myErr: OSErr;
- myDirObj: AEDesc;
- myDataDesc: AEDesc;
- newDesc: AEDesc;
- BEGIN
- PreHandler;
- myErr := errAEEventNotHandled;
- InitSomeDescs(@myDirObj,@myDataDesc,@newDesc,NIL,NIL);
-
- { pick up the direct object, which is the object whose data is to be set }
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyDirectObject,typeWildCard,myDirObj) ,
- 15013 , myErr ) THEN GOTO 9; { finish up }
-
- { now the data to set it to }
- IF CatchErr( AEGetParamDesc(theAppleEvent,keyAEData,typeWildCard,myDataDesc) , 15014 ,
- myErr ) THEN GOTO 9;
-
- { missing any parameters? }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 15015 , myErr ) THEN GOTO 9;
-
- { the direct parameter must be an object - resolve it }
- IF CatchErr( AEResolve(myDirObj,kAEIDoMinimum,newDesc) , 15017 , myErr ) THEN GOTO 9;
-
- { now it's either a token or a "token list" }
- IF newDesc.descriptorType = typeAEList
- THEN gTempBool := CatchErr( SetDataForTokenList(newDesc,myDataDesc) , 15018 , myErr )
- ELSE gTempBool := CatchErr( SetDataForToken(newDesc,myDataDesc) , 15019 , myErr );
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@myDirObj,@myDataDesc,@newDesc,NIL,NIL) , 15020 );
-
- HandleSetData := myErr;
- PostHandler(reply,myErr);
- END; { HandleSetData }
-
-
- {$S QuillNew }
- FUNCTION IndexFromWndwPtr(window: WindowPtr): INTEGER;
- { given a winodw ptr, find its position in the
- front-to-back ordering. If it isn't even a current
- window, return 0.
- INPUTS: window ptr to the window record
- OUTPUTS: window index (0 if it's not even a window)
- ERRORS:
- SIDE EFFECTS:
- }
- VAR i: INTEGER;
- thisWindow: WindowPtr;
- BEGIN
- IndexFromWndwPtr := 0;
- i := 0;
- thisWindow := FrontWindow;
- WHILE thisWindow <> NIL DO
- BEGIN
- i := i+1;
- IF thisWindow = window THEN
- BEGIN { found it }
- IndexFromWndwPtr := i;
- EXIT(IndexFromWndwPtr);
- END;
- { didn't find it - try next window }
- thisWindow := WindowPtr(WindowPeek(thisWindow)^.nextWindow);
- END;
- END; { IndexFromWndwPtr }
-
- {$S Initialize}
- PROCEDURE InitAEHandlers;
- VAR myErr: OSErr;
- BEGIN
- gTempBool := CheckErr( AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,@HandleQuitApp,0,FALSE) , 1013 );
- gTempBool := CheckErr( AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,@HandleOpenDocs,0,FALSE) , 1014 );
- gTempBool := CheckErr( AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,@HandleOpenApp,0,FALSE) , 1015 );
- gTempBool := CheckErr( AEInstallEventHandler(kCoreEventClass,kAEPrint,@HandlePrint,0,FALSE) , 1016 );
-
- gTempBool := CheckErr( AEInstallEventHandler(kAECoreSuite,kAEClose,@HandleClose,0,FALSE) , 1017 );
- gTempBool := CheckErr( AEInstallEventHandler(kAECoreSuite,kAESave,@HandleSave,0,FALSE) , 1018 );
- gTempBool := CheckErr( AEInstallEventHandler(kAECoreSuite,kAEGetData,@HandleGetData,0,FALSE) , 1020 );
- gTempBool := CheckErr( AEInstallEventHandler(kAECoreSuite,kAESetData,@HandleSetData,0,FALSE) , 1021 );
- gTempBool := CheckErr( AEInstallEventHandler(kAEMiscStandards,kAECut,@HandleCut,0,FALSE) , 1022 );
- gTempBool := CheckErr( AEInstallEventHandler(kAEMiscStandards,kAECopy,@HandleCopy,0,FALSE) , 1023 );
- gTempBool := CheckErr( AEInstallEventHandler(kAEMiscStandards,kAEPaste,@HandlePaste,0,FALSE) , 1024 );
- gTempBool := CheckErr( AEInstallEventHandler(kAECoreSuite,kAECountElements,@HandleCountElements,0,FALSE) , 1025 );
- gTempBool := CheckErr( AEInstallEventHandler(kAECoreSuite,kAEMove,@HandleMove,0,FALSE) , 1026 );
-
- { object stuff }
- gTempBool := CheckErr( AEObjectInit , 1027 );
- gTempBool := CheckErr( AESetObjectCallbacks(@MyCompareProc,@MyCountProc,NIL,NIL,NIL,NIL,@MyGetErrorDesc) , 1028 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cWindow,typeNull,@WndwFromNullAccessor,0,FALSE) , 1029 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cDocument,typeNull,@WndwFromNullAccessor,0,FALSE) , 1029 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cWord,typeMyWndw,@TextElemFromWndwAccessor,0,FALSE) , 1030 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cChar,typeMyWndw,@TextElemFromWndwAccessor,0,FALSE) , 1031 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cChar,typeMyWndw,@TextElemFromWndwAccessor,0,FALSE) , 1032 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cSpot,typeMyWndw,@TextElemFromWndwAccessor,0,FALSE) , 1033 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cLine,typeMyWndw,@TextElemFromWndwAccessor,0,FALSE) , 1034 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cItem,typeMyWndw,@TextElemFromWndwAccessor,0,FALSE) , 1035 );
-
- gTempBool := CheckErr( AEInstallObjectAccessor(cWord,typeMyDoc,@TextElemFromWndwAccessor,0,FALSE) , 1030 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cChar,typeMyDoc,@TextElemFromWndwAccessor,0,FALSE) , 1031 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cChar,typeMyDoc,@TextElemFromWndwAccessor,0,FALSE) , 1032 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cSpot,typeMyDoc,@TextElemFromWndwAccessor,0,FALSE) , 1033 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cLine,typeMyDoc,@TextElemFromWndwAccessor,0,FALSE) , 1034 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cItem,typeMyDoc,@TextElemFromWndwAccessor,0,FALSE) , 1035 );
-
- gTempBool := CheckErr( AEInstallObjectAccessor(cChar,typeMyText,@TextElemFromTextAccessor,0,FALSE) , 1036 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cSpot,typeMyText,@TextElemFromTextAccessor,0,FALSE) , 1037 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cWord,typeMyText,@TextElemFromTextAccessor,0,FALSE) , 1038 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cLine,typeMyText,@TextElemFromTextAccessor,0,FALSE) , 1039 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cItem,typeMyText,@TextElemFromTextAccessor,0,FALSE) , 1040 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cProperty,typeMyWndw,@PropFromWndwAccessor,0,FALSE) , 1041 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cProperty,typeMyDoc,@PropFromWndwAccessor,0,FALSE) , 1041 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cProperty,typeMyText,@PropFromTextAccessor,0,FALSE) , 1042 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cProperty,typeNull,@PropFromAppAccessor,0,FALSE) , 1043 );
- gTempBool := CheckErr( AEInstallObjectAccessor(cListElem,typeWildCard,@ElemFromAnythingAccessor,0,FALSE) , 1044 );
- gTempBool := CheckErr( AEInstallObjectAccessor(typeWildCard,typeAEList,@AnythingFromListAccessor,0,FALSE) , 1045 );
-
-
- gTempBool := CheckErr( AEInstallCoercionHandler(typeObjectSpecifier,typeMyWndw,@CoerceObjToAnything,0,TRUE,FALSE) , 1046 ) ;
- gTempBool := CheckErr( AEInstallCoercionHandler(typeObjectSpecifier,typeMyDoc,@CoerceObjToAnything,0,TRUE,FALSE) , 1046 ) ;
- gTempBool := CheckErr( AEInstallCoercionHandler(typeObjectSpecifier,typeMyText,@CoerceObjToAnything,0,TRUE,FALSE) , 1047 ) ;
- gTempBool := CheckErr( AEInstallCoercionHandler(typeObjectSpecifier,typeMyWndwProp,@CoerceObjToAnything,0,TRUE,FALSE) , 1048 ) ;
- gTempBool := CheckErr( AEInstallCoercionHandler(typeObjectSpecifier,typeMyTextProp,@CoerceObjToAnything,0,TRUE,FALSE) , 1049 ) ;
- gTempBool := CheckErr( AEInstallCoercionHandler(typeObjectSpecifier,typeMyAppProp,@CoerceObjToAnything,0,TRUE,FALSE) , 1050 ) ;
- gTempBool := CheckErr( AEInstallCoercionHandler(typeObjectSpecifier,typeStyledText,@CoerceObjToAnything,0,TRUE,FALSE) , 1051 ) ;
- gTempBool := CheckErr( AEInstallCoercionHandler(typeObjectSpecifier,typeChar,@CoerceObjToAnything,0,TRUE,FALSE) , 1052 ) ;
- gTempBool := CheckErr( AEInstallCoercionHandler(typeObjectSpecifier,typeAEList,@CoerceObjToAnything,0,TRUE,FALSE) , 1053 ) ;
- gTempBool := CheckErr( AEInstallCoercionHandler(typeObjectSpecifier,typeMyDoc,@CoerceObjToAnything,0,TRUE,FALSE) , 1054 ) ;
-
- gTempBool := CheckErr( AEInstallCoercionHandler(typeStyledText,typeChar,@CoerceStylTextToText,0,TRUE,FALSE) , 1055 ) ;
-
- gTempBool := CheckErr( AEInstallCoercionHandler(typeMyText,typeStyledText,@CoerceMyTextToStylText,0,TRUE,FALSE) , 1056 ) ;
-
- gTempBool := CheckErr( AEInstallCoercionHandler(typeMyDoc,typeMyWndw,@CoerceMyDocToMyWndw,0,TRUE,FALSE) , 1065 ) ;
-
- gTempBool := CheckErr( AEInstallEventHandler(kAECoreSuite,kAEDelete,@HandleDeleteElement,0,FALSE) , 1026 );
-
- gTempBool := CheckErr( AEInstallCoercionHandler(typeAEList,typeTextStyles,@CoerceListOrValToTextStyles,0,TRUE,FALSE) , 1066 );
- gTempBool := CheckErr( AEInstallCoercionHandler(typeEnumerated,typeTextStyles,@CoerceListOrValToTextStyles,0,TRUE,FALSE) , 1067 );
-
- gTempBool := CheckErr( AEInstallEventHandler(kAECoreSuite,kAECreateElement,@HandleCreateElement,0,FALSE) , 1068 );
-
- gTempBool := CheckErr( AEInstallCoercionHandler(typeStyledText,typeIntlText,@CoerceStylTextToIntlText,0,TRUE,FALSE) , 1069 );
- gTempBool := CheckErr( AEInstallCoercionHandler(typeChar,typeIntlText,@CoerceTextToIntlText,0,TRUE,FALSE) , 1070 );
- gTempBool := CheckErr( AEInstallCoercionHandler(typeIntlText,typeChar,@CoerceIntlTextToText,0,TRUE,FALSE) , 1071 );
-
- { the next, commented-out routine is used when we want to monitor unfamiliar Apple Events that we receive }
- { gTempBool := CheckErr( AEInstallEventHandler(typeWildCard,typeWildCard,@HandleWild,0,FALSE) , 1072 );}
-
- gTempBool := CheckErr( AEInstallEventHandler(kAECoreSuite,kAEDoObjectsExist,@HandleDoObjectsExist,0,FALSE) , 1073 );
-
- END; { InitAEHandlers }
-
- {$S QuillNew2}
- PROCEDURE InitKeyBuffer;
- { this routine initializes the values in the key buffer and
- creates the bufChars handle at its minimum size
- INPUTS: none
- OUTPUTS: none
- NOTES: we might want to do better error handling . . .
- }
- BEGIN
- keyBuffer.bufChars := CharBufHandle(NewHandle(kBufStartSize));
- IF MemError <> noErr THEN
- BEGIN
- DoMyAlert('Trouble in InitKeyBuffer - out of memory!'); { a real error, should be handled better }
- EXIT(InitKeyBuffer);
- END;
- keyBuffer.bufSize := kBufStartSize;
- InitKeyBufVals;
- END; { InitKeyBuffer }
-
- {$S QuillNew2}
- PROCEDURE InitKeyBufVals;
- { this routine intializes some of the values in the
- key buffer to their defaults. It is called when the
- key buffer is first initialized, and after it has been
- emptied. It does NOT size or resize the bufChars handle
- INPUTS: none
- OUTPUTS: none
- 10/03/91 BHM added bufDesc
- }
- BEGIN
- WITH keyBuffer DO
- BEGIN
- bufEmpty := TRUE;
-
- { the following values are supposed to be set by StartKeyBuffering; we'll }
- { give them illegal values that can be easily recognized }
- bufCharCount := -1;
- bufDelCount := -1;
- bufSelStart := -1;
- bufSelEnd := -1;
-
- bufWndw := NIL;
-
- bufDesc := gNullDesc;
- END;
- END; { InitKeyBufVals }
-
-
-
- {$S QuillNew }
- PROCEDURE InitSomeDescs(desc1Ptr, desc2Ptr, desc3Ptr, desc4Ptr, desc5Ptr: DescPtr);
- { set a bunch of descriptors to the null descriptor. The inputs are pointers to
- the descriptors. If one or more of the pointers is NIL, then the routine ignores
- all the inputs after that one (they should be NIL, too). So, for example, if
- desc3Ptr is NIL, only the descriptors pointed to by desc1Ptr and desc2Ptr are
- initialized.
- INPUTS: as above
- OUTPUTS: none
- NOTES: (1) **WARNING** if any of the inputs is NIL, it and all the subsequent
- inputs are ignored
- (2) Because 5 seemed like a nice number, that's why!
- }
- BEGIN
- IF desc1Ptr = NIL THEN EXIT(InitSomeDescs);
- desc1Ptr^ := gNullDesc;
- IF desc2Ptr = NIL THEN EXIT(InitSomeDescs);
- desc2Ptr^ := gNullDesc;
- IF desc3Ptr = NIL THEN EXIT(InitSomeDescs);
- desc3Ptr^ := gNullDesc;
- IF desc4Ptr = NIL THEN EXIT(InitSomeDescs);
- desc4Ptr^ := gNullDesc;
- IF desc5Ptr = NIL THEN EXIT(InitSomeDescs);
- desc5Ptr^ := gNullDesc;
- END; { InitSomeDescs }
-
- {$S QuillNew}
- PROCEDURE InitTextToken(VAR myText: TextToken);
- { initialize a text token to some easily
- recognizable (and usually illegal) values
- INPUTS: myText VAR token to be initialized
- OUTPUTS: none
- }
- BEGIN
- WITH myText DO
- BEGIN
- tokenClass := cNull;
- tokenWndw := NIL;
- tokenOffset := -1;
- tokenLength := -1;
- END;
- END; { InitTextToken }
-
- {$S QuillNew}
- PROCEDURE InitTheStyles;
- { this routine sets up a global data structure, theStyles, which is useful
- when dealing with text styles
- INPUTS: none
- OUTPUTS: none
- }
- BEGIN
- theStyles[1].stylItem := bold;
- theStyles[2].stylItem := italic;
- theStyles[3].stylItem := underline;
- theStyles[4].stylItem := outline;
- theStyles[5].stylItem := shadow;
- theStyles[6].stylItem := condense;
- theStyles[7].stylItem := extend;
-
-
- theStyles[1].stylConst := kAEBold;
- theStyles[2].stylConst := kAEItalic;
- theStyles[3].stylConst := kAEUnderline;
- theStyles[4].stylConst := kAEOutline;
- theStyles[5].stylConst := kAEShadow;
- theStyles[6].stylConst := kAECondensed;
- theStyles[7].stylConst := kAEExpanded;
-
- gAllStyles := [bold,italic,underline,outline,shadow,condense,extend];
- END; { InitTheStyles }
-
- {$S QuillNew2}
- FUNCTION IntlTextToText(intlTextDesc: AEDesc; VAR textDesc: AEDesc;
- VAR scrptCode: ScriptCode; VAR lngCode: LangCode): OSErr;
- { another boring subroutine. Given a descriptor of typeIntlText,
- return a desc containing just the text (typeChar); also return
- the script code and language code.
- INPUTS: intlTextDesc descriptor of typeIntlText
- textDesc return VAR for the typeChar descriptor
- scrptCode return VAR for the script code
- lngCode return VAR for the language code
- OUTPUTS: error code (noErr if none)
- NOTES: even if we return an error because we couldn't create the
- text desc (due to memory problems), scrptCode and lngCode
- will still be valid
- }
- VAR myErr: OSErr;
- myPtr: Ptr;
- textLen: LongInt;
- BEGIN
- WITH intlTextDesc DO
- BEGIN
- HLock(dataHandle);
- myPtr := dataHandle^;
- scrptCode := IntegerPtr(myPtr)^;
-
- myPtr := Ptr(ORD(myPtr) + 2);
- lngCode := IntegerPtr(myPtr)^;
-
- myPtr := Ptr(ORD(myPtr) + 2);
- textLen := GetHandleSize(dataHandle) - 4;
- gTempBool := CatchErr( AECreateDesc(typeChar,myPtr,textLen,textDesc) , 23613 ,
- myErr );
- HUnlock(dataHandle);
- END; { of WITH intlTextDesc }
-
- IntlTextToText := myErr;
- END; { IntlTextToText}
-
-
- {$S QuillNew2}
- FUNCTION ListToStyleSet(stylList: AEDesc; VAR styleSet: Style; VAR plainFlag: BOOLEAN;
- checkStyles: BOOLEAN): OSErr;
- { this routine takes an AEList - presumably of style items, including possibly kAEPlain -
- and returns a corresponding style set (of QD type Style). IF kAEPlain appears in the
- list, then plainFlag is returned TRUE. kAEPlain is ignored in constructing the style set.
- There is also some optional error-checking: if checkStyles is TRUE, then the routine
- aborts if it finds a "bad" item in the list (i.e., not a style item or kAEPlain). If
- checkStyles is FALSE, then the routine ignores bad items altogether.
- INPUTS: stylList the list of style items
- styleSet return VAR for style set
- plainFlag return VAR - TRUE if kAEPlain is in list, FALSE o.w.
- checkStyles if TRUE, abort on bad item; if FALSE, ignore bad
- items
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- itemCount: LongInt;
- i: LongInt;
- badItem: BOOLEAN;
- myItem: DescType;
- stylItem: StyleItem;
- tempPlainFlag: BOOLEAN;
- tErr: OSErr;
- uErr: OSErr;
- junk: LongInt;
- BEGIN
- myErr := genericErr;
- styleSet := [];
- plainFlag := FALSE;
-
- { count the items }
- IF CatchErr( AECountItems(stylList,itemCount) , 22313 , myErr ) THEN GOTO 9;
-
- IF itemCount = 0 THEN GOTO 9; { no styles at all }
-
- FOR i := 1 TO itemCount DO
- BEGIN
- { get the item }
- badItem := (AEGetNthPtr(stylList,i,typeEnumerated,gReturnedKeywd,gReturnedType,
- @myItem,SizeOf(myItem),gActSize) <> noErr);
-
- IF NOT badItem THEN
- BEGIN
- { got an item of typeEnumerated from the list }
- badItem := NOT GetStyleItemFromConst(myItem,stylItem,tempPlainFlag);
-
- IF NOT badItem THEN
- BEGIN
- { got style item (possibly kAEPlain) }
- IF tempPlainFlag THEN plainFlag := TRUE { plainFlag is set to TRUE if ANY item is kAEPlain }
- ELSE styleSet := styleSet + [stylItem]; { got a real style item }
- END; { of: got a style item (possibly kAEPlain) }
-
- END; { of: got a typeEnumerated }
-
- { now check for trouble, if you're supposed to }
- IF checkStyles & badItem THEN
- BEGIN
- gTempBool := CatchErr( errAEBadData , 22314 , myErr );
- GOTO 9; { abort loop }
- END;
-
- END; { of loop }
-
- 9:
- IF myErr <> noErr THEN
- BEGIN
- { just for neatness }
- styleSet := [];
- plainFlag := FALSE;
- END;
-
- ListToStyleSet := myErr;
- END; { ListToStyleSet }
-
-
- {$S QuillNew2}
- FUNCTION MakeElemList(elemClass: DescType; srcText: TextToken;
- VAR elemList: AEDesc): OSErr;
- { given a class of text element (word, item, etc.) and some text,
- make a list of all the elements of that class in the text
- INPUTS: elemClass class of the text element
- srcText text token for the text
- elemList return VAR for the resulting list
- OUTPUTS: error code (noErr if none)
- NOTES: (1) this implementation is inefficient, since for each
- item it starts counting from the beginning of the
- text again; we can speed it up if we want to get clever
- (2) we might want a "count" input parameter; most calling
- routines have already done the count before this
- (3) we don't validate elemClass here because a bad value
- will be picked up by the call to CountTextElems
- }
- LABEL 9;
- VAR myErr: OSErr;
- elemCount: LongInt;
- i: LongInt;
- elemText: TextToken;
- BEGIN
- myErr := genericErr;
-
- { make the empty list }
- IF CatchErr( AECreateList(NIL,0,FALSE,elemList) , 20713 , myErr ) THEN GOTO 9;
-
- { count the text elems }
- IF CatchErr( CountTextElems(srcText,elemClass,elemCount) , 20714 , myErr )
- THEN GOTO 9;
-
- IF elemCount = 0 THEN GOTO 9; { empty list }
-
- { step through the elems }
- FOR i := 1 TO elemCount DO
- BEGIN
- { get a token for the item }
- IF CatchErr( GetTextElemFromText(srcText,elemClass,i,elemText) , 20715 ,
- myErr ) THEN GOTO 9;
-
- { put it in the list }
- IF CatchErr( AEPutPtr(elemList,0,typeMyText,@elemText,SizeOf(elemText)) ,
- 20716 , myErr ) THEN GOTO 9;
- END;
-
- 9:
- { since there are possible errors AFTER the list is created, we will, in the }
- { error case, want to dispose of the list }
-
- IF myErr <> noErr THEN gtempBool := CheckErr( AEDisposeDesc(elemList) , 20717 );
-
- MakeElemList := myErr;
- END; { MakeElemList }
-
- {$S QuillNew2}
- FUNCTION MakeInsertionLoc(relObj: AEDesc; position: DescType;
- VAR insertionLoc: AEDesc): OSErr;
- { this routine takes an object and a position, corresponding to
- the two fields of an insertion loc, and creates the insertion
- loc.
- INPUTS: relObj the "object" field for the insertion loc
- (should be typeObjectSpecifier or typeNull)
- position the "position" field (should be kAEBefore,
- kAEAfter, kAEReplace, kAEBeginning, or kAEEnd)
- theInsLoc return VAR for the insertion loc (a descriptor
- of typeInsertionLoc
- OUTPUTS: error code (noErr if none)
- NOTES: (1) currently we do not validate the inputs
- (2) we use the name "relObj" because the insertion loc is defined
- relative to that object
- }
- LABEL 9;
- VAR myErr: OSErr;
- insLocRec: AEDesc;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@insertionLoc,@insLocRec,NIL,NIL,NIL);
-
- { create AERecord }
- IF CatchErr( AECreateList(NIL,0,TRUE,insLocRec) , 23413 , myErr ) THEN GOTO 9;
-
- { add "object" field }
- IF CatchErr( AEPutKeyDesc(insLocRec,keyAEObject,relObj) , 23414 , myErr )
- THEN GOTO 9;
-
- { add "position" field }
- IF CatchErr( AEPutKeyPtr(insLocRec,keyAEPosition,typeEnumerated,@position,
- SizeOf(position)) , 23415 , myErr ) THEN GOTO 9;
-
- { now coerce to typeInsertionLoc }
- gTempBool := CatchErr( AECoerceDesc(insLocRec,typeInsertionLoc,insertionLoc) , 23416 ,
- myErr);
-
- 9:
- { no need to dispose insertionLoc, even in error case, because creating it is the last thing we do }
-
- gTempBool := CatchErr( AEDisposeDesc(insLocRec) , 23417 , myErr );
-
- MakeInsertionLoc := myErr;
- END; { MakeInsertionLoc }
-
- {$S QuillNew }
- FUNCTION MakeObjSpec(desiredClass: DescType; theCont: AEDesc; keyForm: DescType;
- keyDataType: DescType; keyDataPtr: Ptr; keyDataSize: Size; VAR result: AEDesc): OSErr;
- { makes a descriptor of typeObjectSpecifier out of 4 things: desired class,
- containing object, key form, and key data. The methods of specifying
- the 4 things (simple inputs for class and key form, AEDesc for container,
- type, ptr, and size for key data) may seem oddly mixed, but this is the
- form we most often need it.
- INPUTS: desiredClass class of the object
- theCont container for the object
- keyForm key form for the object
- keyDataType type for key data
- keyDataPtr ptr to key data
- keyDataSize size of key data
- result destination VAR for resulting object specifier
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- NOTES: if MakeObj returns noErr, then result is a valid descriptor that
- the caller is responsible for disposing. If an error code is returned,
- result is undefined and doesn't have to be disposed.
- }
- LABEL 8,9;
- VAR myObjSpecRec: AERecord;
- myErr: OSErr;
- BEGIN
- { create an object specifier record, which is an AERecord }
-
- { start by creating empty record list}
- IF CatchErr( AECreateList(NIL,0,TRUE,myObjSpecRec) , 3613 , myErr )
- THEN GOTO 9; { must set function result }
-
- { add desired class }
- IF CatchErr( AEPutKeyPtr(myObjSpecRec,keyAEDesiredClass,typeType,@desiredClass,SizeOf(desiredClass)) ,
- 3614 , myErr ) THEN GOTO 8; { must dispose of obj spec rec }
-
- { add container }
- IF CatchErr( AEPutKeyDesc(myObjSpecRec,keyAEContainer,theCont) , 3615 , myErr )
- THEN GOTO 8;
-
- { add key form }
- IF CatchErr( AEPutKeyPtr(myObjSpecRec,keyAEKeyForm,typeEnumerated,@keyForm,SizeOf(keyForm)) ,
- 3616 , myErr ) THEN GOTO 8;
-
- { add key data }
- IF CatchErr( AEPutKeyPtr(myObjSpecRec,keyAEKeyData,keyDataType,keyDataPtr,keyDataSize) ,
- 3617 , myErr ) THEN GOTO 8;
-
- { now coerce the AERecord to an object specifier }
- IF CatchErr( AECoerceDesc(myObjSpecRec,typeObjectSpecifier,result) , 3618 , myErr )
- THEN GOTO 8;
-
- { looks good to me }
- myErr := noErr;
-
- 8: { dispose of obj spec rec }
- gTempLong := AEDisposeDesc(myObjSpecRec);
-
- 9: { set function result }
- MakeObjSpec := myErr;
- END; { MakeObjSpec }
-
- {$S QuillNew }
- FUNCTION MakeObjSpecFromIndex(desiredClass: DescType; theCont: AEDesc;
- index: LongInt; VAR result: AEDesc): OSErr;
- { make a descriptor (of typeObjectSpecifier) for an object,
- given its desired class class and an index within a container.
- INPUTS: desiredClass class of the resulting object
- theCont container for the object
- index the index of the object
- result destination VAR for resulting object specifier
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- NOTES: (1) if MakeObjSpecFromIndex returns noErr, then result is a valid
- descriptor that the caller is responsible for disposing. If an
- error code is returned, result is undefined and doesn't have to
- be disposed.
- (2) This is basically a cover proc for MakeObjSpec, which, because of its generality,
- has more inputs than anyone should have to look at very often.
- }
- BEGIN
- MakeObjSpecFromIndex := MakeObjSpec(desiredClass,theCont,formAbsolutePosition,
- typeLongInteger,@index,SizeOf(index),result);
- END; { MakeObjSpecFromIndex }
-
- {$S QuillNew }
- FUNCTION MakeObjSpecFromName(desiredClass: DescType; theCont: AEDesc;
- name: Str255; VAR result: AEDesc): OSErr;
- { make a descriptor (of typeObjectSpecifier) for an object,
- given its desired class, a name, and a container.
- INPUTS: desiredClass class of the resulting object
- theCont container for the object
- name the name of the object
- result destination VAR for resulting object specifier
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- NOTES: (1) if MakeObjSpecFromName returns noErr, then result is a valid
- descriptor that the caller is responsible for disposing. If an
- error code is returned, result is undefined and doesn't have to
- be disposed.
- }
- VAR namePtr: Ptr;
- nameLen: LongInt;
- BEGIN
- namePtr := Ptr(ORD4(@name)+1);
- nameLen := length(name);
- MakeObjSpecFromName := MakeObjSpec(desiredClass,theCont,formName,
- typeChar,namePtr,nameLen,result);
- END; { MakeObjSpecFromName }
-
- {$S QuillNew}
- FUNCTION MakeObjSpecFromRange(desiredClass: DescType; theCont: AEDesc; startObj: AEDesc;
- stopObj: AEDesc; VAR result: AEDesc): OSErr;
- { make a descriptor of typeObjectSpecifier representing a range of things within
- a container.
- INPUTS: desiredClass class of the things in the range
- theCont object containing the range
- startObj starting boundary of the range
- stopObj ending boundary of the range
- result return VAR for resulting obj desc
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- rdRec: AERecord;
- rdDesc: AEDesc;
- keyForm: DescType;
- myObjSpecRec: AEDesc;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@result,@rdRec,@rdDesc,NIL,NIL);
-
- { make the range data record }
- IF CatchErr( AECreateList(NIL,0,TRUE,rdRec) , 13913 , myErr ) THEN GOTO 9;
-
- { attach the boundary objects }
- IF CatchErr( AEPutKeyDesc(rdRec,keyAERangeStart,startObj) , 13914 , myErr ) THEN GOTO 9;
- IF CatchErr( AEPutKeyDesc(rdRec,keyAERangeStop,stopObj) , 13915 , myErr ) THEN GOTO 9;
-
- { coerce the record to a range data descriptor }
- IF CatchErr( AECoerceDesc(rdRec,typeRangeDescriptor,rdDesc) , 13916 , myErr ) THEN GOTO 9; { is that right? }
-
- { create empty record }
- IF CatchErr( AECreateList(NIL,0,TRUE,myObjSpecRec) , 13917 , myErr ) THEN GOTO 9;
-
- { add desired class }
- IF CatchErr( AEPutKeyPtr(myObjSpecRec,keyAEDesiredClass,typeType,@desiredClass,SizeOf(desiredClass)) ,
- 13918 , myErr ) THEN GOTO 9;
-
- { add container }
- IF CatchErr( AEPutKeyDesc(myObjSpecRec,keyAEContainer,theCont) , 13919 , myErr )
- THEN GOTO 9;
-
- { add key form }
- keyForm := formRange;
- IF CatchErr( AEPutKeyPtr(myObjSpecRec,keyAEKeyForm,typeEnumerated,@keyForm,SizeOf(keyForm)) ,
- 13920 , myErr ) THEN GOTO 9;
-
- { add key data }
- IF CatchErr( AEPutKeyDesc(myObjSpecRec,keyAEKeyData,rdDesc) , 13921 , myErr ) THEN GOTO 9;
-
- { now coerce the AERecord to an object specifier }
- IF CatchErr( AECoerceDesc(myObjSpecRec,typeObjectSpecifier,result) , 13922 , myErr )
- THEN GOTO 9;
-
- { note that creating result is the last thing we [try] to do, so even in an }
- { error case there's no need to dispose it }
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@rdRec,@rdDesc,NIL,NIL,NIL) , 13923);
-
- MakeObjSpecFromRange := myErr;
- END; { MakeObjSpecFromRange }
-
- {$S QuillNew2}
- FUNCTION MakePlainList(VAR plainList: AEdesc): OSErr;
- { this is a very silly routine used in a hack to make
- recording of "set style to plain" look a little
- nicer. It creates an AE list containing one item,
- the constant kAEPlain. MakePlainList will almost
- certainly go away after we clean up some of the
- text style stuff
- INPUTS: plainList return VAR for the 1-element list
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- plain: DescType;
- BEGIN
- myErr := genericErr;
-
- { create list }
- IF CatchErr( AECreateList(NIL,0,FALSE,plainList) , 19613 , myErr ) THEN GOTO 9; { finish up }
-
- { add single item to list }
- plain := kAEPlain;
- IF CatchErr( AEPutPtr(plainList,0,typeEnumerated,@plain,SizeOf(plain)) , 19614 , myErr )
- THEN GOTO 9;
-
- 9: { finish up }
- IF myErr <> noErr THEN gTempBool := CheckErr( AEDisposeDesc(plainList) , 19615 );
-
- MakePlainList := myErr;
- END; { MakePlainList }
-
-
- {$S QuillNew }
- FUNCTION MakePropObjSpec(theObj: AEDesc; theProp: DescType;
- VAR result: AEDesc): OSErr;
- { this creates a descriptor of typeObjectSpecifier that respresents
- a particular property of a particular object - as used as parameters
- for GetData and SetData, for example, to get or set properties.
- INPUTS: theObj the object whose property we're talking about
- theProp the property
- result destination VAR for resulting prop object specifier
- ERRORS:
- SIDE EFFECTS:
- NOTES: (1) if MakePropObjSpec returns noErr, then result is a valid
- descriptor that the caller is responsible for disposing. If an
- error code is returned, result is undefined and doesn't have to
- be disposed.
- (2) This is basically a cover proc for MakeObjSpec, which, because of its generality,
- has more inputs than anyone should have to look at very often.
- (3) the input theObj is analogous to theCont in MakeObjSpec and
- related calls, because AppleEvents treats properties as being
- "contained" in the objects they are properties of
- }
- BEGIN
- MakePropObjSpec := MakeObjSpec(cProperty,theObj,formPropertyID,
- typeType,@theProp,SizeOf(theProp),result);
- END; { MakePropObjSpec }
-
- {$S QuillNew }
- FUNCTION MakeSelfAddr(VAR addrDesc: AEAddressDesc): OSErr;
- { create an address descriptor for the current process
- INPUTS: addrDesc result VAR for the descriptor
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- }
- VAR procSerNum: ProcessSerialNumber;
- myErr: INTEGER;
- BEGIN
- procSerNum.highLongOfPSN := 0;
- procSerNum.lowLongOfPSN := kCurrentProcess;
- gTempBool := CatchErr( AECreateDesc(typeProcessSerialNumber,@procSerNum,SizeOf(procSerNum),addrDesc) , 3013 , myErr );
- MakeSelfAddr := myErr;
- END; { MakeSelfAddr }
-
- {$S QuillNew}
- FUNCTION MakeSelTextObj(window: WindowPtr; VAR selTextObj: AEDesc): OSErr;
- { make an object representing the selected text in the given window.
- The object will represent the text as a range of chars within the
- window; the window itself will be represented by index.
- INPUTS: window ptr to the window
- selTextObj return VAR for the text object
- OUTPUTS: error code (noErr if none)
- NOTES: 07/01/91 BHM Added "spots" for 0-length selection (insertion pt)
- 10/04/91 BHM Now replaced by SmartMakeSelTextObj - but I'm leaving
- this here for historical and/or safety reasons
- }
- LABEL 9;
- VAR myErr: OSErr;
- wndwObj: AEDesc;
- startObj: AEDesc;
- endObj: AEDesc;
- index: LongInt;
- startChar: LongInt;
- endChar: LongInt;
- spotFlag: BOOLEAN;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@selTextObj,@wndwObj,@startObj,@endObj,NIL);
-
- { make the window object }
- index := IndexFromWndwPtr(window); { **CHECK for 0? }
- IF CatchErr( MakeObjSpecFromIndex(cDocument,gNullDesc,index,wndwObj) , 16613 , myErr )
- THEN GOTO 9;
-
- { get the start and end of selection }
- WITH DocumentPeek(window)^.docTE^^ DO
- BEGIN
- startChar := selStart+1; { start counting obj's from 1, not 0 }
- endChar := selEnd;
- spotFlag := (selStart = selEnd);
- END;
-
- IF spotFlag THEN
- BEGIN
- { "spots" - 0-length strings - aren't represented as ranges }
- gTempBool := CatchErr( MakeObjSpecFromIndex(cSpot,wndwObj,startChar,selTextObj) , 16617 , myErr );
- GOTO 9;
- END;
-
- { not a spot - must represent as range }
-
- { make obj for start char }
- IF CatchErr( MakeObjSpecFromIndex(cChar,wndwObj,startChar,startObj) , 16614 , myErr)
- THEN GOTO 9;
-
- { now for end char }
- IF CatchErr( MakeObjSpecFromIndex(cChar,wndwObj,endChar,endObj) , 16614 , myErr)
- THEN GOTO 9;
-
- { and now for the whole range object }
- gTempBool := CatchErr( MakeObjSpecFromRange(cChar,wndwObj,startObj,endObj,selTextObj) , 16615 , myErr);
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@wndwObj,@startObj,@endObj,NIL,NIL) , 16616 );
-
- MakeSelTextObj := myErr;
- END; { MakeSelTextObj }
-
- {$S QuillNew2}
- PROCEDURE MakeSelTextToken(window: WindowPtr; VAR selTextToken: TextToken);
- { create a text token representing the selected text (which may be an
- insertion point) in the given window
- INPUTS: window ptr to the window
- selTextToken return VAR for the text token
- OUTPUTS: none
- NOTES: this routine is almost invariably preceded (although not
- necessarily immediately) with a get-and-check front window;
- we may want to roll that in
- }
- BEGIN
- WITH DocumentPeek(window)^.docTE^^ DO
- BEGIN
- selTextToken.tokenOffset := selStart;
- selTextToken.tokenLength := selEnd - selStart;
- END;
-
- selTextToken.tokenWndw := window;
- selTextToken.tokenClass := cText;
- END; { MakeSelTextToken }
-
-
- {$S QuillNew2}
- FUNCTION MakeSpotObj(wndwIndex: INTEGER; spotIndex: INTEGER; VAR spotObj: AEDesc): OSErr;
- { create an object specifier for the "spot" (0-length text object) with a given
- index, and in a window given by its index
- INPUTS: wndwIndex index of the window
- spotIndex index for the spot
- spotObj return VAR for the object specifier
- OUTPUTS: error code (noErr if none)
- NOTES: (1) this is a purely abstract obj spec-constructing routine; we
- don't validate the window, nor how many spots it has
- (2) we may want to make use of this in MakeSelTextObj
- }
- LABEL 9;
- VAR myErr: OSErr;
- wndwObj: AEDesc;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@wndwObj,@spotObj,NIL,NIL,NIL);
-
- { make the window object }
- IF CatchErr( MakeObjSpecFromIndex(cDocument,gNullDesc,wndwIndex,wndwObj) , 19413 , myErr )
- THEN GOTO 9;
-
- { make the spot object }
- gTempBool := CatchErr( MakeObjSpecFromIndex(cSpot,wndwObj,spotIndex,spotObj) , 19414 , myErr );
-
- 9: { finish up }
- { NOTE: you never have to dispose spotObj; either this routine succeeds or spotObj is never even created }
- gTempBool := CheckErr( AEDisposeDesc(wndwObj) , 19415 );
-
- MakeSpotObj := myErr;
- END; { MakeSpotObj }
-
-
-
- {$S QuillNew}
- FUNCTION MakeStylTextDesc(myTextToken: TextToken; VAR theSTDesc: AEDesc): OSErr;
- { given a text token specifying some text in a window,
- return an AERecord containing the text and its style
- information
- INPUTS: myTextToken the text token
- theSTDesc return VAR for the resulting descriptor (in this case an AERecord)
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- textDesc: AEDesc;
- theWndwTE: TEHandle;
- myStylHndl: StScrpHandle;
- oldSTDesc: AEDesc;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@oldSTDesc,@textDesc,@theSTDesc,NIL,NIL);
-
- { create the empty record }
- IF CatchErr( AECreateList(NIL,0,TRUE,oldSTDesc) , 13313 , myErr )
- THEN GOTO 9;
-
- { make a descriptor containing the style-less text}
- IF CatchErr( TextTokenToDesc(myTextToken,textDesc) , 13314 , myErr )
- THEN GOTO 9;
-
- { attach it to the record }
- IF CatchErr( AEPutKeyDesc(oldSTDesc, keyAEText,textDesc) , 13315 , myErr )
- THEN GOTO 9;
-
- { now get the style info - well, first we have to set things up }
- WITH myTextToken DO
- BEGIN
- { **NOTE: this changes the selection. Should we save and reset? }
- theWndwTE := DocumentPeek(tokenWndw)^.docTE;
- TESetSelect(tokenOffset,tokenOffset+tokenLength,theWndwTE);
- END;
-
- myStylHndl := GetStylScrap(theWndwTE);
- IF myStylHndl = NIL THEN
- BEGIN
- gTempBool := CatchErr( stylHndlErr , 13316 , myErr ); { or whatever }
- GOTO 9;
- END;
-
- { now add that info to the record }
- HLock(Handle(myStylHndl));
- myErr := AEPutKeyPtr(oldSTDesc,keyAEStyles,typeScrapStyles,Ptr(myStylHndl^),GetHandleSize(Handle(myStylHndl)));
- HUnlock(Handle(myStylHndl));
- IF CheckErr( myErr , 13317 ) THEN GOTO 9;
-
- { now - **AND do I need this? Is it legit? - coerce the record to typeStyledText }
- IF CatchErr( AECoerceDesc(oldSTDesc,typeStyledText,theSTDesc) , 13318 , myErr )
- THEN GOTO 9;
-
- { all looks fine }
- myErr := noErr; { not really necessary - when is it? }
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@oldSTDesc,@textDesc,NIL,NIL,NIL) , 13319 );
-
- MakeStylTextDesc := myErr;
- END; { MakeStylTextDesc }
-
- {$S QuillNew2}
- FUNCTION MakeTextRangeObj(wndwIndex: INTEGER; startChar: INTEGER; endChar: INTEGER;
- VAR rangeObj: AEDEsc): OSErr;
- { make an object specifier representing the range of characters from startChar to endChar
- (inclusive) in a given window (specified by its index)
- INPUTS: wndwIndex index of the window
- startChar number of the first char in the range
- endChar number of the last char in the range
- rangeObj return VAR for the object specifier
- OUTPUTS: error code (noErr if none)
- NOTES: (1) this is a purely abstract obj-spec-maker; we don't
- validate the window, the number of chars within it, etc.
- (2) I'm using integers for my indices, but it might be
- better to use LongInts - **CHECK
- (3) we may want to make use of this in MakeSelTextObj
- }
- LABEL 9;
- VAR myErr: OSErr;
- wndwObj: AEDesc;
- startObj: AEDesc;
- endObj: AEDesc;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@wndwObj,@startObj,@endObj,@rangeObj,NIL);
-
- { make the window object }
- IF CatchErr( MakeObjSpecFromIndex(cDocument,gNullDesc,wndwIndex,wndwObj) , 19513 , myErr )
- THEN GOTO 9;
-
- { make obj for start char }
- IF CatchErr( MakeObjSpecFromIndex(cChar,wndwObj,startChar,startObj) , 19514 , myErr)
- THEN GOTO 9;
-
- { now for end char }
- IF CatchErr( MakeObjSpecFromIndex(cChar,wndwObj,endChar,endObj) , 19515 , myErr)
- THEN GOTO 9;
-
- { and now for the whole range object }
- gTempBool := CatchErr( MakeObjSpecFromRange(cChar,wndwObj,startObj,endObj,rangeObj) , 19516 , myErr);
-
- 9: { finish up }
- { NOTE: in no case do you need to dispose of rangeObj; if the call fails, then it was never even created }
- gTempBool := CheckErr( DisposeSomeDescs(@wndwObj,@startObj,@endObj,NIL,NIL) , 19517);
-
- MakeTextRangeObj := myErr;
- END; { MakeTextRangeObj }
-
-
- {$S QuillNew}
- PROCEDURE MakeTextTokenForWndw(window: WindowPtr; VAR wndwText: TextToken);
- { given a window, create a text token that represents all the text
- in the window.
- INPUTS: window ptr to the window
- wndwText return VAR for the text token
- OUTPUTS: none
- }
- BEGIN
- WITH wndwText DO
- BEGIN
- tokenClass := cChar; { treat as a range of chars }
- tokenWndw := window;
- tokenOffset := 0;
- tokenLength := DocumentPeek(window)^.docTE^^.teLength;
- END;
- END; { MakeTextTokenForWndw }
-
- {$S QuillNew2}
- FUNCTION MakeWindowList(VAR wndwList: AEDesc; myType: DescType): OSErr;
- { make a list of tokens for all the current windows (used, for example,
- when accessing "all windows") - you can specify whether you want them
- labeled as windows (typeMyWndw) or documents (typeMyDoc)
- INPUTS: wndwList return VAR for window list
- myType type to be used in tokens (typeMyWndw or
- typeMyDoc)
- OUTPUTS: error code (noErr if none)
-
- 09/09/91 BHM added myType param to handle documents
- }
- LABEL 9;
- VAR myErr: OSErr;
- window: WindowPtr;
- BEGIN
- myErr := genericErr;
- wndwList := gNullDesc;
-
- { make the empty list }
- IF CatchErr( AECreateList(NIL,0,FALSE,wndwList) , 19913 , myErr )
- THEN GOTO 9;
-
- { step through the windows }
- window := FrontWindow;
- WHILE window <> NIL DO
- BEGIN
- IF CatchErr( AEPutPtr(wndwList,0,myType,@window,SizeOf(window)) , 19914 , myErr )
- THEN GOTO 9;
- window := WindowPtr(WindowPeek(window)^.nextWindow);
- END;
-
- 9:
- { there are possible errors AFTER the return list is created; if }
- { there's an error, we'll want to dispose of the list }
-
- IF myErr <> noErr THEN gTempBool := CheckErr( AEDisposeDesc(wndwList) , 19915 );
- MakeWindowList := myErr;
- END; { MakeWindowList }
-
- {$S QuillNew2}
- FUNCTION MatchToReqList(srcDesc: AEDesc; reqList: AEDesc; bestType: DescType;
- defType: DescType; VAR dstDesc: AEDesc): OSErr;
- { given a descriptor and a list of types, go down the list and attempt to
- coerce the descriptor into the type you find; continue until you succeed.
- If you come across typeBest, used the supplied bestType value; if you come
- across typeWildCard, use the supplied defType. If NONE of the listed types
- succeed, we'll give one last try with typeWildCard (that is, we'll try defType).
-
- For convenience, if the reqList is either a null descriptor (typeNull) or
- a 0-element list, we treat it as typeWildCard.
-
- INPUTS: srcDesc the given descriptor
- reqList prioritized list of requested types
- bestType type to use for typeBest
- defType type to use for typeWildCard
- dstDesc return VAR for the coerced descriptor
- OUTPUTS: error code (noErr if none)
- NOTES: (1) routines like this, in many cases, do a lot more copying than Quill
- really needs (for example, if dstDesc is already of the right type),
- and we may want to change it or be more particular about when we call
- it in the future - **CHECK
- (2) CAUTION - you may NOT use typeBest as a value for bestType or defType;
- if the AEM got a coercion request with typeBest (in the AECoerce, below),
- it wouldn't know what to do. (Putting in typeWildCard for bestType or
- defType doesn't make much sense either, but probably wouldn't cause an error)
- }
- LABEL 9;
- VAR myErr: OSErr;
- itemCount: LongInt;
- i: LongInt;
- myType: DescType;
- BEGIN
- myErr := genericErr;
- dstDesc := gNullDesc;
-
- { make sure reqList isn't the null descriptor }
- IF reqList.descriptorType <> typeNull THEN
- BEGIN
- { not null desc - should be list; count the items }
- IF CatchErr( AECountItems(reqList,itemCount) , 23813 , myErr ) THEN GOTO 9;
-
- { make sure list isn't empty }
- IF itemCount <> 0 THEN
- BEGIN
-
- FOR i := 1 TO itemCount DO
- BEGIN
- { get ith type in the list }
- IF CatchErr( AEGetNthPtr(reqList,i,typeType,gReturnedKeywd,gReturnedType,@myType,
- SizeOf(myType),gActSize) , 23814 , myErr ) THEN GOTO 9;
-
- { check against "magic" types }
- IF myType = typeBest THEN myType := bestType
- ELSE IF myType = typeWildCard THEN myType := defType;
-
- { we could **CHECK for typeBest here if we wanted to - it shouldn't occur }
-
- myErr := AECoerceDesc(srcDesc,myType,dstDesc);
- IF myErr = noErr THEN GOTO 9; { successful coercion, we're done }
- END; { of loop }
-
- END; { of itemCount <> 0 }
- END; { of reqList not null desc }
-
- { we only get here if (a) reqList is null desc, or (b) reqList has 0 items, or (c) we }
- { failed on every type in the list. In ANY of those cases, we need to try defType. }
-
- gTempBool := CatchErr( AECoerceDesc(srcDesc,defType,dstDesc) , 23815 , myErr );
-
- 9:
- MatchToReqList := myErr;
- END; { MatchToReqList }
-
- {$S QuillNew }
- FUNCTION MightWeInteract(interMode: LongInt; VAR mayInteract: BOOLEAN): OSErr;
- { this is a somewhat special-purpose routine I use in the PrintDocs Event
- handler. Based on the interMode (which is generally obtained from the
- SendMode attr of an AppleEvent), it MAY call AEInteractWithUser and
- report on the results. Here's the rules:
- (1) if interMode = kAENeverInteract, it doesn't call AEInteractWithUser,
- always returns FALSE in mayInteract, and always returns a noErr result
- (2) if interMode = kAECanInteract, it calls AEInteractWithUser. If that
- call fails, FALSE is returned in mayInteract; but the routine returns
- a noErr (i.e., you can't interact, but you should keep going, since the
- mode was only "can" interact, not always). If the AEInteractWithUser
- succeeds, TRUE is returned in mayInteract and noErr as a function
- result
- (3) if interMode = kAEAlwaysInteract, it calls AEInteractWithUser; if that
- call succeeds, TRUE is returned in mayInteract and noErr as a function
- result; but if it fails, FALSE is returned in mayInteract and the error
- code from AEInteractWithUser is returned as a function result (because this
- is an "always" interact case, so we fail if we can't interact)
- INPUTS: interMode one of the 3 interaction mode constants
- mayInteract result VAR to tell the user if it's ok to go
- ahead with some interactive activity (TRUE if ok,
- FALSE o.w.)
- OUTPUTS: error code, noErr if none. Note that the "never" and "can"
- cases don't generate an error regardless of the result of
- AEInteractWithUser
- SIDE EFFECTS: may bring the app forward for interaction
- NOTES: (1) if interMode is an illegal value (not one of the 3),
- we return errAEUnknownSendMode
- (2) AEInteractWithUser is called with no time-out,
- no Notification Manager record, and no idle proc
- }
- LABEL 9;
- VAR myErr: OSErr;
- BEGIN
- myErr := genericErr;
- mayInteract := FALSE;
-
- IF interMode = kAENeverInteract THEN
- BEGIN
- myErr := noErr;
- mayInteract := FALSE;
- GOTO 9; { finish up }
- END;
-
- IF interMode = kAECanInteract THEN
- BEGIN
- myErr := noErr;
- mayInteract := ( AEInteractWithUser(kNoTimeOut,NIL,NIL) = noErr );
- GOTO 9;
- END;
-
- IF interMode = kAEAlwaysInteract THEN
- BEGIN
- myErr := AEInteractWithUser(kNoTimeOut,NIL,NIL);
- mayInteract := (myErr = noErr);
- GOTO 9;
- END;
-
- { illegal interMode value }
-
- myErr := errAEUnknownSendMode;
-
- 9: { finish up }
- MightWeInteract := myErr;
- END; { MightWeInteract }
-
- {$S QuillNew2}
- FUNCTION MoveToken(theToken: AEDesc; relObjToken: AEDesc; position: DescType): OSErr;
- { this routine takes a token representing a single object and moves the object
- to a given location. The location is specified by an object token (relObjToken)
- and a position modifier (position). If position is kAEBefore, kAEAfter, or
- kAEReplace, then the the object is moved to before, after, or into (replacing)
- the relObjToken; if it's kAEBeginning or kAEEnd, then the relObjToken is treated
- as a container, and the object is moved into it at its beginning or end.
-
- IMPORTANT NOTE: relObjToken is assumed to be a token, already resolved, not
- a raw object specifier (if we're doing a list, we don't want
- to resolve it every time through this routine); and it must
- specify a single object, not a list of objects
-
- INPUTS: theToken token representing a single object to be moved
- relObjToken another token used (with position) to specify the
- location to move the first object to
- position an enumerated value used to help specify the location
- to move the first object to
-
- See the above description for valid values and interpretations of relObjToken
- and position
- }
- LABEL 9;
- VAR myErr: OSErr;
- myWndw: WindowPtr;
- relObjType: DescType; { token type, not class of original obj }
- bWindow: WindowPtr;
- BEGIN
- myErr := genericErr;
-
- { windows/docs are the only thing we know how to move right now }
- IF (theToken.descriptorType <> typeMyWndw) & (theToken.descriptorType <> typeMyDoc) THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 23213 , myErr );
- GOTO 9;
- END;
-
- { get the window/doc}
- IF CatchErr( MyAECoerceDescPtr(theToken,typeWildCard,@myWndw,SizeOf(myWndw),gActSize) ,
- 23214 , myErr ) THEN GOTO 9;
-
- { now work out the parameters for MySendWindow }
- { NOTE that we know at least one window exists, so we don't have to worry about empty container }
-
- relObjType := relObjToken.descriptorType; { handy info to have around }
-
- IF position = kAEBeginning THEN
- BEGIN
- { relObjToken better be null }
- IF relObjType <> typeNull THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 23215 , myErr );
- GOTO 9;
- END;
-
- { let's rephrase this as "before the first window" }
- position := kAEBefore;
- bWindow := FrontWindow; { guaranteed to exist }
- END
-
- ELSE IF position = kAEEnd THEN
- BEGIN
- IF relObjType <> typeNull THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 23216 , myErr );
- GOTO 9;
- END;
-
- { let's rephrase this as "after the last window" }
- position := kAEAfter;
- bWindow := BackWindow; { guaranteed to exist }
- END
-
- ELSE
- BEGIN
- { we're in the before/after/replace case; get the other window }
- IF (relObjType <> typeMyWndw) & (relObjType <> typeMyDoc) THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 23217 , myErr );
- GOTO 9;
- END;
-
- { get the window/doc }
- IF CatchErr( MyAECoerceDescPtr(relObjToken,typeWildCard,@bWindow,SizeOf(bWindow),gActSize) ,
- 23214 , myErr ) THEN GOTO 9;
- END;
-
- { we are now set up for MySendWindow }
- gTempBool := CatchErr( MySendWindow(myWndw,bWindow,position) , 23215 , myErr );
-
- 9:
- MoveToken := myErr;
- END; { MoveToken }
-
- {$S QuillNew2}
- FUNCTION MoveTokenList(theList: AEDesc; relObjToken: AEDesc; position: DescType): OSErr;
- { this routine takes a list of tokens (or a list whose ultimate nodes are tokens;
- we permit lists of lists, etc.) and moves every object in the list to a particular
- location. We work backwards through the list to preserve order and minimize side-effects.
-
- Two parameters (relObjToken and position) determine where the objects are to be moved to.
- relObjToken should already be resolved, and should be a token, not a list of tokens.
-
- Naturally, this routine really just iterates through the list and hands over any tokens
- it finds to MoveToken. See that routine for a description of the parameters.
-
- INPUTS: see MoveToken
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- itemCount: LongInt;
- i: LongInt;
- thisItem: AEDesc;
- BEGIN
- myErr := genericErr;
- thisItem := gNullDesc;
-
- IF CatchErr( AECountItems(theList,itemCount) , 23113 , myErr ) THEN GOTO 9;
- IF itemCount = 0 THEN GOTO 9; { empty list, we're done }
-
- { loop through the items }
- FOR i := itemCount DOWNTO 1 DO
- BEGIN
- { get the item }
- IF CatchErr( AEGetNthDesc(theList,i,typeWildCard,gReturnedKeywd,thisItem) , 23114 ,
- myErr ) THEN GOTO 9;
-
- { dispatch on list vs. non-list }
- IF thisItem.descriptorType = typeAEList THEN
- BEGIN
- IF CatchErr( MoveTokenList(thisItem,relObjToken,position) , 23115 , myErr )
- THEN GOTO 9;
- END
- ELSE
- BEGIN
- IF CatchErr( MoveToken(thisItem,relObjToken,position) , 23116 , myErr )
- THEN GOTO 9;
- END;
-
- { dispose of item }
- gTempBool := CheckErr( AEDisposeDesc(thisItem) , 23117 );
- thisItem := gNullDesc;
- END; { FOR loop }
-
- 9:
- gTempBool := CheckErr( AEDisposeDesc(thisItem) , 23118 );
- MoveTokenList := myErr;
- END; { MoveTokenList }
-
- {$S QuillNew }
- FUNCTION MyAEChangeDescType(VAR theDesc: AEDesc; newType: DescType): OSErr;
- { this routine takes an existing descriptor, coerces it to a new type,
- and returns it in the same descriptor. The caller is responsible for
- disposing of that one descriptor, regardless of whether the call fails
- or succeeds.
- INPUTS: theDesc the descriptor to be changed
- newType the type to coerce it to
- OUTPUTS: error code (noErr if none). If the call fails, then the
- descriptor is unchanged
- ERRORS:
- SIDE EFFECTS:
- }
- LABEL 9;
- VAR myErr: OSErr;
- newDesc: AEDesc;
- BEGIN
- myErr := AECoerceDesc(theDesc,newType,newDesc);
- IF myErr <> noErr THEN GOTO 9; { must set function result }
- myErr := AEDisposeDesc(theDesc);
- IF myErr <> noErr THEN GOTO 9;
- theDesc := newDesc; { **CHECK - is this legit? }
- 9: { set function result }
- MyAEChangeDescType := myErr;
- END; { MyAEChangeDescType }
-
- {$S QuillNew}
- FUNCTION MyAECoerceDescPtr(theAEDesc: AEDesc; toType: DescType; dataPtr: Ptr;
- maximumSize: Size; VAR actualSize: Size): OSErr;
- { this routine plugs a hole that's been nagging at me in the AppleEvents
- interface. It takes a descriptor and coerces it to a desired type; but
- instead of returning a descriptor, it returns data in a buffer specified
- by the caller.
- INPUTS: theAEDesc descriptor to be coerced
- toType type to coerce it to
- dataPtr ptr to data buffer
- maximumSize maximum length in bytes of data to be returned
- actualSize actual length in bytes of data for the descriptor
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- NOTES: 12/16/91 BHM (1) Changed to avoid unecessary duplication when the type
- doesn't really change (this should also enable it to handle
- typeWildCard better)
- (2) We don't need to dispose of newDesc because it is a direct
- copy (not a duplicate) of either theAEDesc or resultDesc - that
- is, it contains the same handle
- }
- LABEL 9;
- VAR myErr: INTEGER;
- newDesc: AEDesc;
- resultDesc: AEDesc;
- transferSize: Size;
- BEGIN
- myErr := errAECoercionFail;
- resultDesc := gNullDesc;
-
- { to avoid unnecessary duplication, check old type vs. new type }
- IF (theAEDesc.descriptorType = toType) OR (toType = typeWildCard)
- THEN newDesc := theAEDesc
- ELSE
- BEGIN
- { must coerce to new type }
- IF QuietCatchErr( AECoerceDesc(theAEDesc,toType,resultDesc) , myErr ) THEN GOTO 9;
- newDesc := resultDesc;
- END;
-
- WITH newDesc DO
- BEGIN
- { get the size }
- actualSize := GetHandleSize(dataHandle);
- IF QuietCatchErr( MemError , myErr ) THEN GOTO 9;
-
- { calculate number of bytes to move }
- transferSize := actualSize;
- IF maximumSize < transferSize THEN transferSize := maximumSize;
-
- { move the data }
- HLock(dataHandle);
- BlockMove(dataHandle^,dataPtr,transferSize);
- HUnlock(dataHandle);
- END; { of WITH newDesc }
-
- { everything fine }
- myErr := noErr;
-
- 9: { finish up }
- gTempBool := CheckErr( AEDisposeDesc(resultDesc) , 2215 );
- MyAECoerceDescPtr := myErr;
- END; { MyAECoerceDescPtr }
-
- {$S QuillNew2}
- PROCEDURE MyAEDoKey(key: CHAR; window: WindowPtr);
- { this routine is called after we've handled a keydown
- event (one that generates a character or a delete, not
- a cmd-key event); it does what's necessary to record
- typing for AppleEvents. The character is added to a
- buffer; later, when a non-key event takes place, the
- buffer is bundled up as a text desc and shipped off in
- a Set Data event to replace the selection (or, at least,
- the selection as it was when the user started typing).
- The delete key requires special handling (and, if it's
- the first key to go into the buffer, VERY special handling).
-
- Note that the AppleEvent, when it's sent, will be marked
- "record only"; we've already changed the text in real-time
- when the user was typing.
-
- INPUTS: key the character that was typed
- window ptr to the active window
- OUTPUTS: none
- NOTES: we may want to do some more sophisticated
- error-handling
- }
- BEGIN
- IF keyBuffer.bufEmpty THEN StartKeyBuffering(key,window)
- ELSE ContinueKeyBuffering(key,window);
- END; { MyAEDoKey }
-
-
- {$S QuillNew}
- PROCEDURE MyBringWndwFront(window: WindowPtr);
- { this routine sends an AppleEvent Move event to move
- the given window to before the front window (thus
- bringing the window to the front)
- INPUTS: window ptr to the window
- OUTPUTS: none
- }
- LABEL 9;
- VAR index: INTEGER;
- wndwObj: AEDesc;
- insertionLoc: AEDesc;
- myAppleEvent: AppleEvent;
- defReply: AppleEvent;
- BEGIN
- InitSomeDescs(@wndwObj,@myAppleEvent,@defReply,@insertionLoc,NIL);
-
- index := IndexFromWndwPtr(window);
-
- IF index = 0 THEN
- BEGIN
- { no such window }
- DoMyErr( errAEBadData , 19213 );
- GOTO 9;
- END;
-
- { make an object for the given window }
- IF CheckErr( MakeObjSpecFromIndex(cDocument,gNullDesc,index,wndwObj) , 19214 ) THEN GOTO 9;
-
- { create the insertion loc ("beginning of null container") }
- IF CheckErr( MakeInsertionLoc(gNullDesc,kAEBeginning,insertionLoc) , 19216 ) THEN GOTO 9;
-
- { create the AppleEvent }
- IF CheckErr( AECreateAppleEvent(kAECoreSuite,kAEMove,gSelfAddrDesc,kAutoGenerateReturnID,kAnyTransactionID,myAppleEvent) ,
- 19216 ) THEN GOTO 9;
-
- { add direct object to AppleEvent }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyDirectObject,wndwObj) , 19217 ) THEN GOTO 9;
-
- { add insertion loc to AppleEvent }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyAEInsertHere,insertionLoc) , 19218 ) THEN GOTO 9;
-
-
- { send AppleEvent }
- gTempBool := CheckErr( AESend(myAppleEvent,defReply,kAENoReply+kAECanInteract,kAENormalPriority,kAEDefaultTimeOut,NIL,NIL) ,
- 19219 );
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@wndwObj,@myAppleEvent,@defReply,@insertionLoc,NIL) , 19220 );
- END; { MyBringWndwFront }
-
- {$S QuillNew}
- FUNCTION MyCompareProc(oper: DescType; obj1: AEDesc; obj2: AEDesc; VAR result: BOOLEAN): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- aDesc: AEDesc;
- bDesc: AEDesc;
- BEGIN
- MyCompareProc := genericErr;
- InitSomeDescs(@aDesc,@bDesc,NIL,NIL,NIL);
-
- { get two text descriptors }
- IF NOT(AECanCompare(obj1.descriptorType)) THEN
- BEGIN
- IF CatchErr( GetTextFromDesc(obj1,aDesc) , 15813 , myErr ) THEN GOTO 9;
- END
- ELSE
- BEGIN
- IF CatchErr( AEDuplicateDesc(obj1,aDesc) , 15817 , myErr ) THEN GOTO 9;
- END;
-
- IF NOT(AECanCompare(obj2.descriptorType)) THEN
- BEGIN
- IF CatchErr( GetTextFromDesc(obj2,bDesc) , 15814 , myErr ) THEN GOTO 9;
- END
- ELSE
- BEGIN
- IF CatchErr( AEDuplicateDesc(obj2,bDesc) , 15818 , myErr ) THEN GOTO 9;
- END;
-
- { now, compare them }
- IF CatchErr( AEStandardCompare(oper, aDesc, bDesc, result) , 15815 , myErr ) THEN GOTO 9;
-
- 9:
- gTempBool := CheckErr( DisposeSomeDescs(@aDesc,@bDesc,NIL,NIL,NIL), 15816);
- MyCompareProc := myErr;
-
- END; { MyCompareProc }
-
-
- {$S QuillNew}
- FUNCTION MyCountProc(desiredType: DescType; containerClass: DescType;
- container: AEDesc; VAR result: LongInt): OSErr;
- { so far all I count is:
- (1) the number of active windows in the app;
- (2) the number of chars/words/lines/items/spots in a window or some text
- I realized that I wasn't really using the containerClass, so I wrote an
- "inner" routine that doesn't take that parameter (and is useful elsewhere)
- }
- BEGIN
- MyCountProc := RealCountProc(desiredType,container,result);
- END; { MyCountProc }
-
- {$S QuillNew }
- FUNCTION MyCreateFSS(fileName: Str255; VAR fileSpec: FSSpec): OSErr;
- { use the current default volume and directory to create a file
- spec from a file name
- INPUTS: fileName intended name for the file
- fileSpec result VAR for file spec
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- }
- VAR theVRefNum: INTEGER;
- theDirID: LongInt;
- myErr: INTEGER;
- name: Str255;
- BEGIN
- myErr := HGetVol(@name,theVRefNum,theDirID);
- IF myErr = noErr THEN WITH fileSpec DO
- BEGIN
- vRefNum := theVRefNum;
- parID := theDirID;
- name := fileName;
- END;
- MyCreateFSS := myErr;
- END; { MyCreateFSS }
-
- {$S QuillNew}
- FUNCTION MyDoCopy(window: WindowPtr): OSErr;
- { copy the selection from the specified
- window and put it into the desk scrap
- INPUTS: window ptr to the window
- OUTPUTS: error code (noErr if none)
- NOTES: (1) this is straight from TEStyleSample; I'm not sure
- why it's so different from their Cut routine.
- }
- LABEL 9;
- VAR myErr: OSErr;
- BEGIN
- IF CatchErr( ZeroScrap , 17713 , myErr ) THEN GOTO 9;
- TECopy(DocumentPeek(window)^.docTE);
- 9:
- MyDoCopy := myErr;
- END; { MyDoCopy }
-
-
- {$S QuillNew}
- FUNCTION MyDoCut(window: WindowPtr): OSErr;
- { cut the selection from the the specified window
- and put it into the desk scrap.
- INPUTS: window the window
- OUTPUTS: error code (noErr if none)
- NOTES: **CHECK - I'm just going by TEStyleSample here . . . .
- (apparently new-style TE records don't need TEFromScrap
- and TEToScrap) Also, I'm not sure what errors I want
- to hand back. I'll get back to this.
- }
- LABEL 9;
- VAR myErr: OSErr;
- total: LongInt;
- contig: LongInt;
- myTEHndl: TEHandle;
- BEGIN
- myErr := genericErr;
-
- IF CatchErr( ZeroScrap , 17413 , myErr ) THEN GOTO 9;
-
- PurgeSpace(total,contig);
-
- myTEHndl := DocumentPeek(window)^.docTE;
- IF myTEHndl^^.selEnd - myTEHndl^^.selStart + kTESlop > contig THEN
- BEGIN
- gTempBool := CatchErr( memFullErr , 17414 , myErr ); { **CHECK - TEStyleSample triggered eNoSpaceCut }
- GOTO 9;
- END;
-
- TECut(myTEHndl);
- DirtyWindow(window);
- myErr := noErr;
-
- 9: { finish up }
- MyDoCut := myErr;
- END; { MyDoCut }
-
- {$S QuillNew}
- FUNCTION MyDoPaste(window: WindowPtr): OSErr;
- { paste whatever's in the desk scrap into the selection
- in the given window.
- INPUTS: window ptr to the window
- OUTPUTS: error code (noErr if none)
- NOTES: (1) this is taken right from TEStyleSample, and can
- probably stand some improvement
- (2) this is good enough for the menu Paste command,
- but may have to get smarter when we put in the
- other parameters the Paste event can have - **CHECK
- }
- LABEL 9;
- VAR myErr: OSErr;
- myTEHndl: TEHandle;
- aHandle: Handle;
- oldSize: LongInt;
- newSize: LongInt;
- BEGIN
- myErr := genericErr;
-
- myTEHndl := DocumentPeek(window)^.docTE;
-
- WITH myTEHndl^^ DO
- IF TEGetScrapLen + teLength - (selEnd - selStart) > kMaxTELength THEN
- BEGIN
- { too big to be pasted in }
- gTempBool := CatchErr( errCantPaste , 18113 , myErr ); { TEStyleSample triggers eExceedPaste here }
- GOTO 9;
- END;
-
- aHandle := Handle(TEGetText(myTEHndl));
- oldSize := GetHandleSize(aHandle);
- newSize := oldSize + TEGetScrapLen + kTESlop;
- SetHandleSize(aHandle,newSize);
- myErr := MemError;
- SetHandleSize(aHandle,oldSize);
-
- IF CheckErr( myErr , 18114 ) THEN GOTO 9; { TEStyleSample triggers eNoSpacePaste here }
-
- TEStylPaste(myTEHndl);
- DirtyWindow(window);
- myErr := noErr;
-
- 9: { finish up }
-
- MyDoPaste := myErr;
- END; { MyDoPaste }
-
-
- {$S QuillNew}
- FUNCTION MyGetTextElem(textPtr: Ptr; textLength: LongInt; delChar: SignedByte;
- elemIndex: LongInt; VAR elemOffset: LongInt; VAR elemLength: LongInt): OSErr;
- { this routine is used to find lines or items in a piece of text. The text is
- given by a ptr to its first char and a length (which can be 0). The delChar
- is used to delimit elements: if delChar = carriage return then you're talking
- about lines, if = comma then items. (Any other character could also be used.)
- The particular element is given by its index within the text: 1 for the first
- such element, 2 for the second, etc. The routine returns an offset (from textPtr)
- to the first character of the element, and the length of the element.
-
- An element is any delimiter-free stretch of contiguous bytes between two
- delimiters - except that the text boundaries also delimit elements, so e.g.
- all the characters up to (but not including) the first delimiter character
- constitute the first element. (Same for all the chars after the last delmiter,
- mutatis mutandis.) Elements can be of 0 length, e.g. the item between two
- adjacent commas. The element does not include the delimiters.
- Any text has at least one element; even 0-length text has exactly one
- 0-length line (also, one 0-length item).
-
- INPUTS: textPtr ptr to first char of the text
- textLength length of the text; characters after this are ignored
- delChar delimiter character
- elemIndex number of the element within the text (1 for first element,
- 2 for second, etc.)
- elemOffset return VAR for offset from textPtr to the first char of
- the element (an offset of 0 refers to the first char of the text)
- elemLength return VAR for the length of the element
- OUTPUTS: noErr if the element is found; errAEIllegalIndex if there aren't that many
- elements, or if elemIndex < 0; errAECorruptData if textLength < 0
- NOTES: **IMPORTANT - this routine is NOT used to get words or characters. It's
- only for lines and items.
- }
- LABEL 9;
- VAR myErr: OSErr;
- endPtr: Ptr;
- endPlus1Ptr: Ptr;
- elemPtr: Ptr;
- elemCount: LongInt;
- delPtr: Ptr;
- BEGIN
- myErr := errAEIllegalIndex; { most likely error, if any }
- elemOffset := -1;
- elemLength := -1; { illegal values, easily recognized }
-
- IF textLength < 0 THEN
- BEGIN
- myErr := errAECorruptData; { bad text }
- GOTO 9;
- END;
-
- IF elemIndex < 0 THEN GOTO 9; { bad index }
-
- endPtr := Ptr(ORD(textPtr) + textLength - 1); { ptr to last char of text }
- { NOTE: for 0-length text, endPtr is 1 LESS then textPtr; our lower-level
- routines know how to deal with this. See e.g. ScanToDelimiter }
- endPlus1Ptr := Ptr(ORD(endPtr) + 1); { handy to have around }
-
- elemPtr := textPtr;
- elemCount := 1;
-
- WHILE TRUE DO { repeat forever, sort of }
- BEGIN
- { we come in at the start of an element; let's get its end }
- ScanToDelimiter(elemPtr,endPtr,delChar,delPtr);
-
- { now, is it the right element? }
- IF elemCount = elemIndex THEN
- BEGIN
- { yes }
- elemOffset := ORD(elemPtr) - ORD(textPtr);
- elemLength := ORD(delPtr) - ORD(elemPtr);
- myErr := noErr;
- GOTO 9;
- END;
-
- { not the right element, try the next }
- IF delPtr = endPlus1Ptr THEN GOTO 9; { there isn't any next element }
-
- { yes, there is, and here's where it starts }
- elemPtr := Ptr(ORD(delPtr)+1);
- elemCount := elemCount+1;
- END; { of WHILE loop }
-
- 9: { finish up}
- MyGetTextElem := myErr;
- END; { MyGetTextElem }
-
- {$S QuillNew}
- FUNCTION MyGetWord(textPtr: Ptr; textLength: LongInt; wordIndex: LongInt;
- VAR wordOffset: LongInt; VAR wordLength: LongInt): OSErr;
- { find the nth word in a piece of text. The text is given by a ptr to
- its first char and a length. The word is specified by its index in the
- text (1 for first word, 2 for second, etc.). The routine returns an
- offset (from textPtr) to the first char of the word, and the word's
- length.
-
- A word is any stretch of contiguous bytes that contains no break characters,
- is of positive length, and is bounded by break characters and/or the start
- of the text and/or the end of the text. Even text with no break characters
- can contain a word (the text "alpha" has 1 word). However, some text contains
- no words at all, e.g. a run of 17 spaces. Text with 0 length contains no words.
- By definition a word cannot be of length 0.
-
- Break characters are defined by the routines ScanToBreak and ScanToNonBreak.
- As currently implemented, they think spaces and carriage returns are breaks,
- and nothing else.
-
- INPUT: textPtr ptr to first char of text
- textLength length of the text
- wordIndex number of the word in the text (1 for first word,
- 2 for second, etc.)
- wordOffset return VAR for offset from textPtr of first char
- of the word (an offset of 0 refers to the first
- char of the text)
- wordLength return VAR for the length of the word
- OUTPUTS: noErr if the word is found; errAEIllegalIndex if there aren't that
- many words, or if wordIndex < 0; errAECorruptData if textLength < 0
- }
- LABEL 9;
- VAR myErr: OSErr;
- endPtr: Ptr;
- endPlus1Ptr: Ptr;
- wordPtr: Ptr;
- wordCount: LongInt;
- breakPtr: Ptr;
- BEGIN
- myErr := errAEIllegalIndex; { most likely error, if any }
- wordOffset := -1;
- wordLength := -1; { illegal values, easily recognized }
-
- IF textLength < 0 THEN
- BEGIN
- myErr := errAECorruptData; { bad text }
- GOTO 9;
- END;
-
- IF wordIndex < 0 THEN GOTO 9; { bad index }
- IF textLength < 1 THEN GOTO 9; { no words, easy fail }
-
-
- IF wordIndex < 0 THEN GOTO 9; { bad index }
-
-
- IF textLength < 1 THEN GOTO 9; { bad index }
-
- endPtr := Ptr(ORD(textPtr) + textLength - 1); { ptr to last char of text }
- endPlus1Ptr := Ptr(ORD(endPtr) + 1); { useful to have around }
-
- { go to start of first word }
- ScanToNonBreak(textPtr,endPtr,wordPtr);
-
- IF wordPtr = endPlus1Ptr THEN GOTO 9; { there is no first word }
-
- wordCount := 1;
-
- WHILE TRUE DO { repeat forever, sort of }
- BEGIN
- { we come in at the start of a word; let's get to its end }
- ScanToBreak(wordPtr,endPtr,breakPtr);
-
- { now, is it the right word? }
- IF wordCount = wordIndex THEN
- BEGIN
- { yes }
- wordOffset := ORD(wordPtr) - ORD(textPtr);
- wordLength := ORD(breakPtr) - ORD(wordPtr);
- myErr := noErr;
- GOTO 9;
- END;
-
- { not the right word, try the next }
- ScanToNonBreak(breakPtr,endPtr,wordPtr); { this works even if breakPtr = endPtr + 1 }
- IF wordPtr = endPlus1Ptr THEN GOTO 9; { no next word }
-
- { we're at the start of the next word }
- wordCount := wordCount+1;
- END; { of WHILE loop }
-
- 9: { finish up }
- MyGetWord := myErr;
- END; { MyGetWord }
-
- {$S QuillNew}
- FUNCTION MyGetUniformStyles(theTE: TEHandle; VAR onStyles: Style; VAR offStyles: Style): OSErr;
- { put each style item that is on across the whole selection
- into onStyles, each style item that is off across the
- whole selection into offStyles. The selection is mixed
- respect to those style items that don't show up in
- onStyles or offStyles.
- INPUT: theTE handle to the TE record
- onStyles return VAR for subset of style items ON
- for whole selection
- offStyles return VAR for subset of style items OFF
- for whole selection
- OUTPUT: error code (noErr if none)
- NOTES: (1) if this routine is working right, then the intersection
- of onStyles and offStyles should be empty
- (2) we don't really need to lock handles, since we're only
- acessing fields, but it makes me feel better
- (3) **CHECK how this does with 0-length selections
- (4) there don't seem to be any error conditions . . . .
- (maybe NIL myStylRuns should be an error, since it can
- happen for several reasons - and may mean something in
- the future as well)
- (5) using GetStylScrap seems more stable than walking
- the TEStyleHandle (and associated data structures) myself;
- it's also (a) easier and (b) less efficient
- }
- LABEL 9;
- VAR myErr: OSErr;
- notOffStyles: Style;
- myStylRuns: StScrpHandle;
- i: INTEGER;
- runStyle: Style;
- BEGIN
- myErr := noErr;
- onStyles := gAllStyles;
- { we'll whittle that down later }
- notOffStyles := []; { and build this up }
-
- myStylRuns := GetStylScrap(theTE);
-
- IF myStylRuns = NIL THEN
- BEGIN
- { old-style TERecord - everything's uniform }
- { **CHECK - how about memory or other errors? }
- onStyles := theTE^^.txFace;
- notOffStyles := onStyles;
- myErr := noErr;
- GOTO 9;
- END;
-
- HLock(Handle(myStylRuns));
-
- WITH myStylRuns^^ DO
- BEGIN
- FOR i := 0 TO (scrpNStyles - 1) DO
- BEGIN
- runStyle := scrpStyleTab[i].scrpFace;
- onStyles := onStyles * runStyle;
- notOffStyles := notOffStyles + runStyle;
- END; { of FOR }
- END; { of WITH myStylRuns^^ }
-
- myErr := noErr;
-
- 9: { finish up }
-
- IF myStylRuns <> NIL THEN DisposHandle(Handle(myStylRuns));
- offStyles := gAllStyles - notOffStyles;
-
- MyGetUniformStyles := myErr;
- END; { MyGetUniformStyles }
-
-
- {$S QuillNew }
- FUNCTION MyMakeFSSForWndw(window: WindowPtr; VAR theFSS: FSSpec): OSErr;
- { this routine will attempt to come up with a file spec for a given window.
- Its plan of attack is:
- (1) if the window doc record has a valid FSSpec in it, then return that.
- (2) if not, then concoct an FSSpec from the window title and the default
- directory and path
- The file spec is returned in theFSS. If the call fails, then theFSS is
- marked invalid (vRefNum = badVRefNum).
- The routine will not create the file for you, nor tell you if it already
- exists. It also doesn't "mark" the window doc record with the resulting
- FSSpec. You can do it yourself, if you want to.
- INPUTS: window ptr to the window
- theFSS result VAR for the file spec (if the call fails, it
- will have its vRefNum set to badVRefNum)
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- }
- VAR wndwTitle: Str255;
- myErr: OSErr;
- BEGIN
- WITH DocumentPeek(window)^ DO
- BEGIN
- IF docFile.vRefNum <> badVRefNum THEN
- BEGIN
- { file spec in doc record is good }
- theFSS := docFile;
- MyMakeFSSForWndw := noErr;
- EXIT(MyMakeFSSForWndw);
- END;
- END;
-
- { file spec in doc record wasn't good - concoct one }
- GetWTitle(window,wndwTitle);
- myErr := FSMakeFSSpec(0,0,wndwTitle,theFSS);
- { note that fnfErr is ok here; it just means the file doesn't exist yet }
- IF myErr = fnfErr THEN myErr := noErr; { so discard that error }
- IF myErr <> noErr THEN theFSS.vRefNum := badVRefNum;
- MyMakeFSSForWndw := myErr;
- END; { MyMakeFSSForWndw }
-
-
- {$S QuillNew }
- FUNCTION MyNewWindow(VAR window: WindowPtr): OSErr;
- { create a new window document and make it the front window
- INPUTS: window return VAR for ptr to new window
- OUTPUTS: error code (noErr if none)
- SIDE EFFECTS:
- NOTES: this is a major rewrite of DoNew for Quill.
- Some differences:
- (1) returns ptr to the window, error code
- (2) offsets new window position from front window (if any)
- (3) keeps track of total number of docs created (from app
- startup) to make up a default name
- (4) marks new document docFile.vRefNum with badVRefNum (no valid file yet)
- (5) and it's generally cleaner
- }
- LABEL 6,7,8,9;
- VAR myErr: OSErr;
- wndwStorage: Ptr;
- oldFront: WindowPtr;
- destRect: Rect;
- viewRect: Rect;
- newTitle: Str255;
- BEGIN
- myErr := genericErr;
- window := NIL;
-
- IF gNumDocuments >= kMaxOpenDocuments THEN
- BEGIN
- gTempBool := CatchErr( errTooManyDocs , 20113 , myErr );
- GOTO 9; { clean up }
- END;
-
- { get storage for new window document record }
- wndwStorage := NewPtr(SizeOf(DocumentRecord));
- IF CatchErr( MemError , 20114 , myErr ) THEN GOTO 9;
-
- oldFront := FrontWindow; { need this later for positioning }
-
- window := GetNewWindow(rDocWindow,wndwStorage,WindowPtr(-1));
- IF window = NIL THEN
- BEGIN
- gTempBool := CatchErr( errNoNewWindow , 20115 , myErr );
- GOTO 8; { call fails - must dispose of storage }
- END;
-
- { we've got a window }
- { if there was a previous front window, offset position of the new one }
- IF oldFront <> NIL THEN WITH oldFront^.portBits.bounds DO
- MoveWindow(window,45 - left,45 - top,TRUE); { the numbers are a little funny to satisfy MoveWindow }
-
- SetPort(window);
- WITH window^, DocumentPeek(window)^ DO
- BEGIN
- { set up all the fields of the window doc }
-
- docFile.vRefNum := badVRefNum; { no valid file yet }
-
- { set up new-style TE record }
- GetTERect(window,viewRect);
- destRect := viewRect;
- destRect.right := destRect.left + kMaxDocWidth;
-
- docTE := TEStylNew(destRect,viewRect);
- IF docTE = NIL THEN
- BEGIN
- gTempBool := CatchErr( errNoNewTE , 20116 , myErr );
- GOTO 7; { call fails - must close window }
- END;
-
- TEAutoView(TRUE,docTE);
- docClik := docTE^^.clikLoop;
- docTE^^.clikLoop := @AsmClikLoop;
-
- docVScroll := GetNewControl(rVScroll,window);
- IF docVScroll = NIL THEN
- BEGIN
- gTempBool := CatchErr( errNoNewControl , 20117 , myErr );
- GOTO 6; { call fails - must get rid of docTE }
- END;
-
- docHScroll := GetNewControl(rHScroll,window);
- IF docHScroll = NIL THEN
- BEGIN
- gTempBool := CatchErr( errNoNewControl , 20118 , myErr );
- GOTO 6; { call fails - must get rid of docTE }
- END;
-
- { got all the data structures we need; call will succeed }
- AdjustScrollValues(window,FALSE);
-
- { the number of currently open windows - will be decremented when we close a window }
- gNumDocuments := gNumDocuments+1;
-
- { the number of windows that have been opened since app startup -
- used for default title; won't be decremented }
- gDocCount := gDocCount+1;
-
- newTitle := Concat('Untitled #',MyNumToStr(gDocCount));
- SetWTitle(window,newTitle);
-
- CleanWindow(window); { windows are born clean }
-
- { we're fine - finish up }
- ShowWindow(window);
- myErr := noErr;
- GOTO 9; { skip error handling }
-
-
-
- { call fails - error handling }
- { we'll do these two inside the WITH , because that's where they originated }
- { neatness counts }
-
- 6: { dispose of docTE }
- TEDispose(docTE);
-
- 7: { close down window }
- CloseWindow(window);
-
- END; { of big WITH }
-
- { one last piece of error handling }
- 8: { dispose of window storage (CloseWindow doesn't do that for you) }
- DisposPtr(Ptr(window));
-
- 9: { finish up }
- MyNewWindow := myErr;
- END; { MyNewWindow }
-
- {$S QuillNew}
- FUNCTION MyNumToStr(theNum: LONGINT): Str255;
- { function version of NumToString
- INPUTS: theNum number to be converted to string
- OUTPUTS: resulting string
- ERRORS:
- SIDE EFFECTS:
- }
- VAR resStr: Str255;
- BEGIN
- NumToString(theNum,resStr);
- MyNumToStr := resStr;
- END; { MyNumToStr }
-
- {$S QuillNew}
- FUNCTION MyOpenWindow(myFSSpec: FSSpec): OSErr;
- { open a new window for the given file. If there's
- already a window open for it, bring it to the front
- INPUTS: myFSSpec the file
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- }
- LABEL 9;
- VAR myErr: OSErr;
- window: WindowPtr;
- BEGIN
- myErr := genericErr;
- { maybe it's already open - if it is, should we just make that the
- front window, or should we "refill it" from the file?
- (I'll just make it front, for now) }
-
- window := FrontWindow;
- WHILE window <> NIL DO
- BEGIN
- IF EqualFSSpecs(DocumentPeek(window)^.docFile,myFSSpec) THEN
- BEGIN
- SelectWindow(window);
- myErr := noErr;
- GOTO 9; { finish up }
- END;
- window := WindowPtr(WindowPeek(window)^.nextWindow);
- END;
-
- { need a new window }
- IF CatchErr( MyNewWindow(window) , 20313 , myErr ) THEN GOTO 9;
- SetWTitle(window,myFSSpec.name);
- WITH DocumentPeek(window)^ DO
- BEGIN
- IF CatchErr( FileToTERec(myFSSpec,docTE) , 20314 , myErr ) THEN GOTO 9;
- InvalRect(docTE^^.viewRect); { **CHECK - this have to be locked? }
- docFile := myFSSpec;
- END;
-
- 9: { finish up }
- MyOpenWindow := myErr;
- END; { MyOpenWindow }
-
- {$S QuillNew}
- FUNCTION MySendWindow(aWindow: WindowPtr; bWindow: WindowPtr;
- whereMod: DescType): OSErr;
- { move a window's place in the front-to-back ordering so that
- it is either in front of, behind, or replacing a given window
- INPUTS: aWindow the window to be moved
- bWindow the "reference window" that aWindow is
- to be moved in front of, behind, or into
- whereMod kAEBefore, kAEAfter, or kAEReplace
- OUTPUTS: error code (noErr if none)
- NOTES: (1) in the "into" (replacing) case, bWindow will be eliminated
- without saving
- (2) we might be better off with a "set window index" routine
- here (but I don't think so)
- (3) if you're modifying this routine, see IMPORTANT NOTE below
- }
- LABEL 9;
- VAR myErr: OSErr;
- aIndex: INTEGER;
- bIndex: INTEGER;
- cIndex: INTEGER;
- cWndw: WindowPtr;
-
- PROCEDURE CorrectVis;
- { this makes some vis region adjustments needed when the
- the SendBehind call actually moves a window closer to
- the front. See Inside Mac I-286.
- INPUTS: none
- OUTPUTS: none
- NOTES: wholely owned by MySendWindow
- }
- VAR wPeek: WindowPeek;
- BEGIN
- wPeek := WindowPeek(aWindow);
- PaintOne(wPeek,wPeek^.strucRgn);
- CalcVis(wPeek);
- END; { CorrectVis }
-
-
- BEGIN
- myErr := genericErr;
-
- IF (whereMod <> kAEBefore) & (whereMod <> kAEAfter) & (whereMod <> kAEReplace) THEN
- BEGIN
- myErr := errAEBadData; { or whatever }
- GOTO 9;
- END;
-
- aIndex := IndexFromWndwPtr(aWindow);
- bIndex := IndexFromWndwPtr(bWindow);
- IF (aIndex = 0) | (bIndex = 0) THEN
- BEGIN
- { at least one of these isn't a current window }
- myErr := errAEBadData;
- GOTO 9;
- END;
-
- { IMPORTANT NOTE: }
- { after this point in the code there is nothing that can generate an error; so }
- { since it's convenient for the code, I'll set myErr = noErr here. Think of }
- { it as the noErr result of the last test, above. But if you change the code }
- { around, be careful! }
-
- myErr := noErr;
-
- IF aWindow = bWindow THEN GOTO 9; { windows are the same, no action necessary }
-
- IF whereMod = kAEAfter THEN
- BEGIN
- IF aIndex = bIndex + 1 THEN GOTO 9; { aWindow already right behind bWindow, save yourself the bother }
-
- { otherwise, send aWindow behind bWindow }
- SendBehind(aWindow,bWindow);
- IF aIndex > bIndex + 1 THEN CorrectVis;
- GOTO 9;
- END;
-
- IF whereMod = kAEReplace THEN
- BEGIN
- SendBehind(aWindow,bWindow);
- IF aIndex > bIndex + 1 THEN CorrectVis;
- ShutTheWindow(bWindow);
- GOTO 9;
- END;
-
- IF whereMod = kAEBefore THEN
- BEGIN
- IF aIndex = bIndex - 1 THEN GOTO 9; { aWindow already in front of bWindow, save yourself the bother }
-
- { otherwise: if bWindow is front, make aWindow front }
- IF bIndex = 1 THEN SelectWindow(aWindow)
- ELSE
- BEGIN
- { here's our situation: bWindow is NOT front, so there's something }
- { in front of it - call it cWindow. We want to put aWindow in }
- { front of bWindow, so we'll put it just behind cWindow. We KNOW }
- { aWindow <> cWindow, because of the "aIndex = bIndex - 1" test }
- { above (this was a glitch in an earlier version) }
-
- cIndex := bIndex - 1;
- cWndw := WndwPtrFromIndex(cIndex);
- SendBehind(aWindow,cWndw);
- IF aIndex > cIndex + 1 THEN CorrectVis;
- END;
- END;
-
- 9: { finish up }
- MySendWindow := myErr;
- END; { MySendWindow }
-
- {$S QuillNew}
- FUNCTION MyRandom(count: LongInt): LongInt;
- { return a random integer between 1 and count, inclusive
- INPUTS: count upper bound for random number
- OUTPUTS: a random integer between 1 and count, inclusive
- NOTES: **CHECK - this is a quick, dirty, and WRONG version
- to be used for testing only
- }
- VAR longRandom: LongInt;
- BEGIN
- longRandom := $10000*Random + Random;
- MyRandom := (ABS(longRandom) MOD count) + 1;
- END; { MyRandom }
-
- {$S QuillNew }
- FUNCTION MyTerminate(saveOpt: DescType; VAR userCancelled: BOOLEAN): OSErr;
- { tell the event loop to quit the app by setting gQuitNow to TRUE.
- saveOpt can be kAEYes (save all docs, don't bother user), kAENo
- (don't save), or kAEAsk (ask the user on each file). In the
- "ask user" case, use AEInteractWithUser before interacting. Also
- in the "ask user" case, give the user the option to cancel each step
- of the way; if cancel, then return without quitting
- INPUTS: saveOpt save, don't save, or ask user
- userCancelled result VAR, returns TRUE if user cancelled,
- FALSE o.w.
- OUTPUTS: error code - interaction trouble, file-and-mem trouble,
- or whatever (noErr if no error). User cancellation is
- NOT an error
- ERRORS;
- SIDE EFFECTS: may bring app to front for user interaction; also
- gets rid of some AE data structures that are used
- globally
- NOTES: if the call fails, we don't quit. In a real app we would
- want better error handling
- }
- LABEL 9;
- VAR myErr: OSErr;
- BEGIN
- myErr := genericErr;
- userCancelled := FALSE;
-
- IF CatchErr( SmartCloseAll(saveOpt,userCancelled) , 8313 , myErr ) THEN GOTO 9; { set function result }
- IF userCancelled THEN
- BEGIN
- MyTerminate := noErr; { user cancelled - it's not an error }
- EXIT(MyTerminate); { but don't quit app }
- END;
-
- { dispose of global gSelfAddrDesc }
- IF CatchErr( AEDisposeDesc(gSelfAddrDesc) , 8315 , myErr ) THEN GOTO 9;
-
- { everything's fine, so tell the app to quit }
- gQuitNow := TRUE;
- myErr := noErr;
-
- 9: { set function value }
- MyTerminate := myErr;
- END; { MyTerminate }
-
- {$S Main}
- FUNCTION NewPrintText( hTE : TEHandle; useDialog: BOOLEAN ): OSErr;
-
- { Prints the edit record. Opens a printer port, calculates the numbers of lines
- per page (it may be different for each page depending on the the text styles) and
- then calls TEUpdate for the page, scroll a page and TEUpdate, etc. }
- { CHANGES FOR QUILL: added useDialog parameter, gotPrintRec variable;
- routine now skips print dialog and uses default print record if useDialog is FALSE
-
- 01/28/92 BHM Renamed NewPrintText; now returns OSErr, including "user cancelled"
- **CHECK - I squeezed in "user cancelled" check, but it's just a band-aid;
- this routine should be rewritten
- }
-
- CONST
- Margins = 20; { page margins }
-
- VAR gotPrintRec: BOOLEAN;
- totalLines: INTEGER; { number of lines in text }
- rView: Rect; { viewRect for TERect }
- oldPort: grafPtr; { hold original grafPtr }
- oldView: Rect; { hold original viewRect }
- oldDest: Rect; { hold original destRect }
- totalHeight: INTEGER; { lineHeight for TERec }
- currentLine: INTEGER; { what line are we on }
- scrollAmount: INTEGER; { how much we scroll by }
- zeroRect: Rect; { 0,0,0,0 rect used in clipRect }
-
- thePrinterStatus: TPrStatus; { printer status }
- openPrintManager: BOOLEAN; { flag if print manager can be opened okay }
- abort: BOOLEAN; { flag if cmd-period is hit to exit routine }
- viewHeight: INTEGER; { temp that has the viewRect height+1 to test conditions }
-
-
- BEGIN { NewPrintText }
- openPrintManager := FALSE; {printer not open yet}
- IF gPrinterRecord <> NIL THEN BEGIN { do we have a legitimate record?}
- PrOpen; {open mr. print record if okay}
-
- IF useDialog THEN gotPrintRec := PrJobDialog(gPrinterRecord) { bring up print dialog }
- ELSE
- BEGIN { use defaults }
- PrintDefault(gPrinterRecord);
- gotPrintRec := TRUE;
- END;
-
- { here's where it's tossed in }
- IF gotPrintRec THEN NewPrintText := noErr ELSE NewPrintText := errAEUserCancelled;
-
-
- IF gotPrintRec THEN BEGIN {bring up job dialog}
- GetPort( oldPort ); { save the old stuff to restore later }
- oldView := hTE^^.viewRect;
- oldDest := hTE^^.destRect;
- gPrinterPort := PrOpenDoc( gPrinterRecord, NIL, NIL );
- OpenPrintManager := ( PrError = noErr );
- END; { if }
- END; { if }
-
- IF OpenPrintManager THEN BEGIN
- SetPort( grafPtr( gPrinterPort ) ); { printer port is now the current port }
- SetRect( zeroRect, 0, 0, 0, 0 );
-
- rView := gPrinterRecord^^.PrInfo.rPage; { get the size of the page rectangle }
- InsetRect( rView, Margins, Margins ); { adjust it for the margins }
- hTE^^.inPort := GrafPtr( gPrinterPort ); { force TE to look at the printer port }
- hTE^^.destRect := rView;
- hTE^^.viewRect := rView; { set new view and dest rects to the TERec }
- TECalText( hTE ); { recalculate our lineStarts array with the new rects }
- totalLines := hTE^^.nLines; { get the number of lines in the newly sized TERec }
- totalHeight := TEGetHeight( totalLines, 0, hTE );
- hTE^^.destRect.bottom := hTE^^.destRect.top + totalHeight; { how tall our destRect is }
-
- abort := FALSE;
- currentLine := 1; { TextEdit sez that TEGetHeight is 1 not 0 based }
-
- WHILE ( NOT ( abort ) AND ( currentLine <= totalLines ) ) DO BEGIN
- PrOpenPage( gPrinterPort, NIL );
- scrollAmount := 0;
- ClipRect( gPrinterRecord^^.PrInfo.rPage ); { Open clipping so text will be drawn }
-
- viewHeight := hTE^^.viewRect.bottom - hTE^^.viewRect.top + 1;
-
- { figure out how many lines there are per page }
- WHILE ((( scrollAmount + TEGetHeight( currentLine, currentLine, hTE ) ) <= viewHeight )
- AND ( currentLine <= totalLines ) ) DO BEGIN
- scrollAmount := scrollAmount + TEGetHeight( currentLine, currentLine, hTE );
- currentLine := currentLine + 1;
- END; { while }
-
- hTE^^.viewRect.bottom := scrollAmount + Margins; { Add margins since top has a margin }
- TEDeactivate( hTE ); { Deactive the edit record so we don't print the cursor or selection range }
- TEUpdate( hTE^^.viewRect, hTE ); { print the page }
- ClipRect( zeroRect ); { Close clipping so that TEScroll doesn't redraw the text }
- TEScroll( 0, -scrollAmount, hTE ); { scroll the page so we can print the next one }
- hTE^^.viewRect.bottom := rView.bottom; { reset bottom to full page }
-
- IF prError = iPrAbort THEN
- abort := TRUE;
- PrClosePage( gPrinterPort ); { close everything up }
- END; { while }
-
- PrCloseDoc( gPrinterPort );
- IF ( gPrinterRecord^^.prJob.bJDocLoop = bSpoolLoop ) AND ( PrError = noErr ) THEN
- PrPicFile( gPrinterRecord, NIL, NIL, NIL, thePrinterStatus );
- PrClose;
- SetPort( oldPort );
- hTE^^.inPort := oldPort;
- hTE^^.viewRect := oldView; { restore the old stuff when we are done }
- hTE^^.destRect := oldDest;
- TEUpdate( hTE^^.viewRect, hTE ); { update everything after resetting the port }
- END; { if }
- END; { NewPrintText }
-
- {$S QuillNew}
- PROCEDURE PostHandler(reply: AppleEvent; errNum: OSErr);
- { this routine is called at the end of every AppleEvent
- handler, to do any generic stuff we might want done there.
- Right now all it does is set the gInHandler flag, so utility
- routines (most particularly, error-reporting routines) can
- always know if we're in a handler or not
- INPUTS: reply the reply AppleEvent in which the handler
- should return any error parameters; may be
- typeNull if the sender didn't ask for a reply
- myErr the error code generated by the handler (may be noErr)
- OUTPUTS: none
- NOTES: this may go away in the near future
- 09/19/91 BHM Added gErrorDesc stuff
- **CHECK - QUESTION - how should we deal with errors in here?
- }
- VAR errDescExists: BOOLEAN;
- BEGIN
- gInHandler := FALSE;
-
- errDescExists := (gErrorDesc.descriptorType <> typeNull);
-
- IF (reply.descriptorType <> typeNull) & (errNum <> noErr) & errDescExists THEN
- { they want a reply; there was an error; there's an object in gErrorDesc - }
- { so send it back with the reply }
- gTempBool := CheckErr( AEPutParamDesc(reply,keyAEErrorObject,gErrorDesc) , 21313 );
-
- { in any case, if there is a gErrorDesc, now's a good time to get rid of it }
- IF errDescExists THEN
- BEGIN
- gTempBool := CheckErr( AEDisposeDesc(gErrorDesc) , 21314 );
- gErrorDesc := gNullDesc; { just for neatness }
- END;
- END; { PostHandler }
-
- {$S QuillNew}
- PROCEDURE PreHandler;
- { this routine is called at the start of every AppleEvent
- handler, to do any generic stuff we might want done there.
- Right now all it does is set the gInHandler flag, so utility
- routines (most particularly, error-reporting routines) can
- always know if we're in a handler or not
- INPUTS: none
- OUTPUTS: none
- NOTES: this may go away in the near future
- 09/18/91 BHM Added gErrorDesc init (in case a handler doesn't use AEResolve,
- this will make sure we don't get a spurious, left-over error)
- }
- BEGIN
- gInHandler := TRUE;
- gErrorDesc := gNullDesc;
- END; { PreHandler }
-
- {$S QuillNew2}
- FUNCTION PrintFile(myFSS: FSSpec): OSErr;
- { print the text fram a specified file. We use the trick of opening
- a TERec somewhere off the screen, printing it, and throwing it away.
-
- Interaction (i.e., the Print Dialog) is determined by some
- globals, gInterMode and gTriedDialog, originally set by
- HandlePrint. If gInterMode is kAENeverInteract or kAECanInteract,
- skip the Print Dialog and use default print rec values. If
- gInterMode is kAEAlwaysInteract, then look at gTriedDialog to see
- if we've already tried the dialog once for this Print event. (Even
- if we have a list of tokens, we only want to do the dialog once.)
- If gTriedDialog is TRUE, then skip the dialog. If it's FALSE, set
- it to TRUE and try the dialog (and if you can't interact, return an
- error). In any case, don't try the dialog until you're sure you
- have something to print.
-
- INPUTS: myFSS file spec for file to be printed
- OUTPUTS: error code (noErr if none). "user cancelled" is an error.
- SIDE EFFECTS: may change gTriedDialog
- NOTES: it's NewPrintText that actually puts up the dialog, if needed;
- we just call NewPrintText
- }
- LABEL 9;
- VAR myErr: OSErr;
- teHndl: TEHandle;
- destRect: Rect;
- useDialog: BOOLEAN;
- BEGIN
- myErr := genericErr;
- teHndl := NIL;
-
- SetRect(destRect,-500,-500,0,0); { set it offscreen - **CHECK this technique }
- teHndl := TEStylNew(destRect,destRect);
- IF teHndl = NIL THEN
- BEGIN
- gTempBool := CatchErr( errNoNewTE , 1813 , myErr ); { *CHECK better error code - probably a mem error }
- GOTO 9;
- END;
-
- { got a valid TERec, read the file into it }
- IF CatchErr( FileToTERec(myFSS,teHndl) , 1814 , myErr ) THEN GOTO 9;
-
- { now - take care of interaction }
- useDialog := ((gInterMode = kAEAlwaysInteract) | (gInterMode = kAECanInteract)) & (NOT gTriedDialog);
- IF useDialog THEN
- BEGIN
- { should try to use the dialog }
- gTriedDialog := TRUE; { well, nothing can stop me from TRYING to interact now }
- IF CatchErr( AEInteractWithUser(kNoTimeOut,NIL,NIL) , 1815 , myErr ) THEN GOTO 9;
- END;
-
- { if we get here, then we either don't need to interact, or we can }
- gTempBool := CatchErr( NewPrintText(teHndl,useDialog) , 24214 , myErr );
-
- 9:
- IF teHndl <> NIL THEN TEDispose(teHndl);
-
- PrintFile := myErr;
- END; { PrintFile }
-
-
- {$S QuillNew2}
- FUNCTION PrintFileList(theList: AEDesc): OSErr;
- { given a list of files - or, at least, things that can be
- coerced to files - print them all.
-
- Interaction (i.e., the Print Dialog) is handled by PrintFile;
- it depends on the globals gInterMode and gTriedDialog, which
- must be set (usually by HandlePrint) before this routine is
- called.
-
- INPUTS: theList list of files to be printed
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- itemCount: LongInt;
- i: LongInt;
- myFSS: FSSpec;
- BEGIN
- myErr := genericErr;
-
- { count the items }
- IF CatchErr( AECountItems(theList,itemCount) , 24113 , myErr ) THEN GOTO 9;
- IF itemCount = 0 THEN GOTO 9; { empty list, we're done }
-
- { loop through the items }
- FOR i := 1 TO itemCount DO
- BEGIN
- { get the item as a file }
- IF CatchErr( AEGetNthPtr(theList,i,typeFSS,gReturnedKeywd,gReturnedType,@myFSS,
- SizeOf(myFSS),gActSize) , 24114 , myErr ) THEN GOTO 9;
-
- { print it }
- IF CatchErr( PrintFile(myFSS) , 24115 , myErr ) THEN GOTO 9;
- END; { of loop }
-
- 9:
- PrintFileList := myErr;
- END; { PrintFileList }
-
- {$S QuillNew2}
- FUNCTION PrintToken(theToken: AEDesc): OSErr;
- { given a token, print the object it represents. Right now
- we only print windows or documents (files are handled by
- PrintFile).
-
- Interaction (i.e., the Print Dialog) is determined by some
- globals, gInterMode and gTriedDialog, originally set by
- HandlePrint. If gInterMode is kAENeverInteract or kAECanInteract,
- skip the Print Dialog and use default print rec values. If
- gInterMode is kAEAlwaysInteract, then look at gTriedDialog to see
- if we've already tried the dialog once for this Print event. (Even
- if we have a list of tokens, we only want to do the dialog once.)
- If gTriedDialog is TRUE, then skip the dialog. If it's FALSE, set
- it to TRUE and try the dialog (and if you can't interact, return an
- error). In any case, don't try the dialog until you're sure you
- have something to print.
-
- INPUTS: theToken token for object to be printed; should be
- window or document (or coercible to that)
- OUTPUTS: error code (noErr if none). "user cancelled" is treated
- as an error.
- SIDE EFFECTS: may change gTriedDialog
- NOTES: it's NewPrintText that actually puts up the dialog, if needed;
- we just call NewPrintText
- }
- LABEL 9;
- VAR myErr: OSErr;
- myWndw: WindowPtr;
- useDialog: BOOLEAN;
- BEGIN
- myErr := genericErr;
-
- { get the window - docs will coerce to windows }
- IF CatchErr( MyAECoerceDescPtr(theToken,typeMyWndw,@myWndw,SizeOf(myWndw),gActSize) ,
- 24213 , myErr ) THEN GOTO 9;
-
- { figure out the dialog stuff }
- useDialog := (gInterMode = kAEAlwaysInteract) & (NOT gTriedDialog);
- IF useDialog THEN
- BEGIN
- { should try to use the dialog - set up to interact }
- gTriedDialog := TRUE; { well, nothing can stop me from TRYING to interact now }
- IF CatchErr( AEInteractWithUser(kNoTimeOut,NIL,NIL) , 24214 , myErr ) THEN GOTO 9;
- END;
-
- { if we get here, then we either don't need to interact, or we can }
- gTempBool := CatchErr( NewPrintText(DocumentPeek(myWndw)^.docTE,useDialog) , 24215 , myErr );
-
- 9:
- PrintToken := myErr;
- END; { PrintToken }
-
-
- {$S QuillNew2}
- FUNCTION PrintTokenList(theList: AEDesc): OSErr;
- { this routine takes a list of tokens (we permit embedded lists,
- but the ultimate nodes must be tokens) and prints everything in
- it.
-
- Interaction (i.e., the Print Dialog) is handled by PrintToken;
- it depends on the globals gInterMode and gTriedDialog, which
- must be set (usually by HandlePrint) before this routine is
- called.
-
- INPUTS: theList list of tokens to be printed
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- itemCount: LongInt;
- i: LongInt;
- thisItem: AEDesc;
- BEGIN
- myErr := genericErr;
- thisItem := gNullDesc;
-
- { count the items }
- IF CatchErr( AECountItems(theList,itemCount) , 24313 , myErr ) THEN GOTO 9;
- IF itemCount = 0 THEN GOTO 9; { empty list, we're done }
-
- { loop through the items }
- FOR i := 1 TO itemCount DO
- BEGIN
- { get the item }
- IF CatchErr( AEGetNthDesc(theList,i,typeWildCard,gReturnedKeywd,thisItem) ,
- 24114 , myErr ) THEN GOTO 9;
-
- { if it's a list, call yourself recursively }
- IF thisItem.descriptorType = typeAEList THEN
- BEGIN
- IF CatchErr( PrintTokenList(thisItem) , 24314 , myErr ) THEN GOTO 9;
- END
- ELSE
- BEGIN
- { not a list, must be a token - print it }
- IF CatchErr( PrintToken(thisItem) , 24315 , myErr ) THEN GOTO 9;
- END;
-
- { dispose of item for next pass }
- gTempBool := CheckErr( AEDisposeDesc(thisItem) , 24316 );
- thisItem := gNullDesc;
- END; { of loop }
-
- 9:
- gTempBool := CheckErr( AEDisposeDesc(thisItem) , 24317 );
-
- PrintTokenList := myErr;
- END; { PrintTokenList }
-
-
-
- {$S QuillNew}
- FUNCTION PropFromAppAccessor(wantClass: DescType; container: AEDesc ;
- containerClass: DescType; form: DescType; selectionData: AEDesc; VAR value: AEDesc;
- theRefCon: LongInt): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- myProp: DescType;
- BEGIN
- myErr := accessorErr;
- value := gNullDesc;
-
- { the container should be typeNull }
- IF containerClass <> cNull THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 18513 , myErr );
- GOTO 9;
- END;
-
- { get the property }
- IF CatchErr( MyAECoerceDescPtr(selectionData,typeType,@myProp,SizeOf(myProp),gActSize) ,
- 18515 , myErr ) THEN GOTO 9;
-
- { make the token }
- gTempBool := CatchErr( AECreateDesc(typeMyAppProp,@myProp,SizeOf(myProp),value) , 18516 ,
- myErr );
-
- 9: { finish up }
- PropFromAppAccessor := myErr;
- END; { PropFromAppAccessor }
-
- {$S QuillNew}
- FUNCTION PropFromTextAccessor(wantClass: DescType; container: AEDesc ;
- containerClass: DescType; form: DescType; selectionData: AEDesc; VAR value: AEDesc;
- theRefCon: LongInt): OSErr;
- LABEL 9;
- VAR myErr: OSErr;
- myText: TextToken;
- myTextProp: TextPropToken;
- myProp: DescType;
- BEGIN
- myErr := accessorErr; { or whatever }
- value := gNullDesc;
-
- { check a few necessities }
- IF (wantClass <> cProperty) | (form <> formPropertyID) THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 16113 , myErr );
- GOTO 9; { finish up }
- END;
-
- { get the text token }
- IF CatchErr( MyAECoerceDescPtr(container,typeMyText,@myText,SizeOf(myText),gActSize) ,
- 16114 , myErr ) THEN GOTO 9;
-
- { get the property }
- IF CatchErr( MyAECoerceDescPtr(selectionData,typeType,@myProp,SizeOf(myProp),gActSize) ,
- 16115 , myErr ) THEN GOTO 9;
-
- { make the token }
- WITH myTextProp DO
- BEGIN
- tpText := myText;
- tpProp := myProp;
- END;
-
- gTempBool := CatchErr( AECreateDesc(typeMyTextProp,@myTextProp,SizeOf(myTextProp),value) ,
- 16116 , myErr );
-
- 9: { finish up }
- PropFromTextAccessor := myErr;
- END; { PropFromTextAccessor }
-
-
- {$S QuillNew}
- FUNCTION PropFromWndwAccessor(wantClass: DescType; container: AEDesc;
- containerClass: DescType; form: DescType; selectionData: AEDesc; VAR value: AEDesc;
- theRefCon: LongInt): OSErr;
- { NOTES:
- 02/17/92 BHM replaced pText with pContents
- }
- LABEL 9;
- VAR myErr: OSErr;
- window: WindowPtr;
- myProp: DescType;
- myText: TextToken;
- wndwProp: WndwPropToken;
- BEGIN
- myErr := accessorErr; { or whatever }
- value := gNullDesc;
-
- { check a few necessities }
- IF (wantClass <> cProperty) | (form <> formPropertyID) THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 14513 , myErr );
- GOTO 9; { finish up }
- END;
-
- { get the window }
- IF CatchErr( MyAECoerceDescPtr(container,typeMyWndw,@window,SizeOf(window),gActSize) ,
- 14514 , myErr ) THEN GOTO 9;
-
- { get the property }
- IF CatchErr( MyAECoerceDescPtr(selectionData,typeType,@myProp,SizeOf(myProp),gActSize) ,
- 14115 , myErr ) THEN GOTO 9;
-
- { EXPERIMENTAL: special-case pContents; instead of returning a window prop token, return }
- { a text token. This will net us all the text properties/behaviors for free - **CHECK }
-
- IF myProp = pContents THEN
- BEGIN
- MakeTextTokenForWndw(window,myText);
- gTempBool := CatchErr( AECreateDesc(typeMyText,@myText,SizeOf(myText),value) , 14116 , myErr );
- GOTO 9;
- END;
-
- { if it's not pContents, then just build a window prop token }
- WITH wndwProp DO
- BEGIN
- wpWndw := window;
- wpProp := myProp;
- END;
-
- gTempBool := CatchErr( AECreateDesc(typeMyWndwProp,@wndwProp,SizeOf(wndwProp),value) , 14117 , myErr );
-
- 9:
- PropFromWndwAccessor := myErr;
- END; { PropFromWndwAccessor }
-
- {$S QuillNew}
- FUNCTION QuietCatchErr(theErr: OSErr; VAR holdErr: OSErr): BOOLEAN;
- { this routine returns TRUE if theErr is a real error (not
- noErr), FALSE if noErr. In either case it stuffs theErr
- into the VAR parameter holdErr for later use, which can
- be particularly handy if the first parameter is an error-
- generating function (like all the AE calls). Unlike
- CatchErr, QuietCatchErr does not put up an error alert.
- INPUTS: theErr potential error to be checked
- holdERR result VAR to save the error code in
- OUTPUTS: TRUE if theErr is a real error, FALSE if it's noErr
- }
- BEGIN
- holdErr := theErr;
- QuietCatchErr := (theErr <> noErr);
- END; { QuietCatchErr }
-
- {$S QuillNew}
- FUNCTION RealCountProc(desiredType: DescType; container: AEDesc;
- VAR result: LongInt): OSErr;
- { so far all I count is:
- (1) the number of active windows in the app;
- (2) the number of chars/words/lines/items in a window or some text
- In MyCountProc, I noticed that I wasn't really using the containerClass
- parameter, and it turned out to be handy to have a version that didn't
- call for that parameter.
-
- 08/21/91 BHM put in number of list elements in a list
- }
- LABEL 9;
- VAR myErr: OSErr;
- myList: AEDesc;
- window: WindowPtr;
- myText: TextToken;
- BEGIN
- myErr := genericErr;
- result := -1; { easily recognized illegal value }
- myList := gNullDesc;
-
- IF desiredType = cListElem THEN
- BEGIN
- { coerce the container to a list }
- IF CatchErr( AECoerceDesc(container,typeAEList,myList) , 18216 , myErr )
- THEN GOTO 9;
- { and count its elements }
- gTempBool := CatchErr( AECountItems(myList,result) , 18215 , myErr );
- GOTO 9;
- END; { typeAEList }
-
- { **CHECK the next step - should we just check descriptorType directly? }
- IF MyAECoerceDescPtr(container,typeNull,@gTempLong,0,gActSize) = noErr THEN
- BEGIN
- { container is null }
- IF (desiredType <> cWindow) & (desiredType <> cDocument) THEN myErr := errAEWrongDataType
- ELSE
- BEGIN
- { windows out of app }
- result := CountWindows;
- myErr := noErr;
- END;
- GOTO 9; { finish up }
- END; { cNull container }
-
- { container wasn't null; let's try to get it as a text token }
-
- { start with a window }
- IF MyAECoerceDescPtr(container,typeMyWndw,@window,SizeOf(window),gActSize) = noErr
- THEN MakeTextTokenForWndw(window,myText)
- ELSE IF MyAECoerceDescPtr(container,typeMyText,@myText,SizeOf(myText),gActSize ) <> noErr
- THEN
- BEGIN
- { can't get a text token, nothing we can count }
- gTempBool := CatchErr( errAEWrongDataType , 18213 , myErr );
- GOTO 9;
- END;
-
- { now we've got a text token; we can count any of the classes of text elements in it }
- { if desiredType is not a class of text elements, CountTextElems will pick up the error }
- gTempBool := CatchErr( CountTextElems(myText,desiredType,result) , 18214 , myErr );
-
- 9: { finish up }
- gTempBool := CheckErr( AEDisposeDesc(myList) , 18217 );
-
- RealCountProc := myErr;
- END; { RealCountProc }
-
- {$S QuillNew2}
- PROCEDURE ResetKeyBuffer;
- { this routine resizes the key buffer to its minimum size and
- sets up various values in it
- INPUTS: none
- OUPUTS: none
- 10/03/91 BHM added bufDesc}
- BEGIN
- SetHandleSize(Handle(keyBuffer.bufChars),kBufStartSize); { never a grow, so should never fail }
- keyBuffer.bufSize := kBufStartSize;
- gTempBool := CheckErr( AEDisposeDesc(keyBuffer.bufDesc) , 21913 );
- InitKeyBufVals;
- END; { ResetKeyBuffer }
-
-
- {$S QuillNew}
- PROCEDURE ScanToBreak(startPtr: Ptr; endPtr: Ptr; VAR breakPtr: Ptr);
- { starting at startPtr, scan characters until you find a word break
- character, and return a ptr to it. If you get past endPtr and still
- haven't found it, return a ptr to 1 byte beyond endPtr.
- This is a fairly dumb version, in which the only break characters
- are spaces and carriage returns.
- INPUTS: startPtr ptr to first char of text to be scanned
- endPtr ptr to last char of text to be scanned
- breakPtr return VAR for ptr to break character
- OUTPUTS: none
- NOTES: (1) if startPtr is pointing to a break character,
- that's fine; just return it in breakPtr
- (2) a 0-length text is passed into this routine with
- endPtr = startPtr - 1; in this case the routine will
- return endPtr + 1 ( = startPtr), since it can't find
- a break character among the 0 characters available for
- scanning
- }
- BEGIN
- breakPtr := startPtr;
- WHILE ORD(breakPtr) <> ORD(endPtr) + 1 DO
- BEGIN
- IF (breakPtr^ = asciiSpace) | (breakPtr^ = asciiCR) THEN EXIT(ScanToBreak); { found it }
- breakPtr := Ptr(ORD(breakPtr) + 1); { didn't find it, try next }
- END;
- END; { ScanToBreak }
-
- {$S QuillNew}
- PROCEDURE ScanToDelimiter(startPtr: Ptr; endPtr: Ptr; delChar: SignedByte;
- VAR delPtr: Ptr);
- { starting at startPtr, scan until you find a particular dilimiting character,
- and return a ptr to it. If you get to endPtr and still haven't found it,
- return a ptr to 1 byte beyond endPtr. (Conceptually you can imagine a
- delimiter placed at 1 byte beyond endPtr.)
- INPUTS: startPtr ptr to first char of text to be scanned
- endPtr ptr to last char of text to be scanned
- delChar character to be scanned for
- delPtr return VAR for ptr to delimiter
- OUTPUTS: none
- NOTES: (1) if startPtr is pointing to a delimiter character,
- that's fine; just return it in delPtr
- (2) a 0-length text is passed into this routine with
- endPtr = startPtr - 1; in this case the routine will
- return endPtr + 1 ( = startPtr), since it can't find
- a delimiter character among the 0 characters available for
- scanning
- }
- BEGIN
- delPtr := startPtr;
- WHILE ORD(delPtr) <> ORD(endPtr)+1 DO
- BEGIN
- IF delPtr^ = delChar THEN EXIT(ScanToDelimiter); { found it }
- delPtr := Ptr(ORD(delPtr) + 1); { didn't find it, try next }
- END;
- END; { ScanToDelimiter }
-
- {$S QuillNew}
- PROCEDURE ScanToNonBreak(startPtr: Ptr; endPtr: Ptr; VAR nbPtr: Ptr);
- { starting at startPtr, scan characters until you find a non-break
- character, and return a ptr to it. If you get past endPtr and still
- haven't found it, return a ptr to 1 byte beyond endPtr.
- This is a fairly dumb version, in which the only break characters
- are spaces and carriage returns.
- INPUTS: startPtr ptr to first char of text to be scanned
- endPtr ptr to last char of text to be scanned
- breakPtr return VAR for ptr to non-break character
- OUTPUTS: none
- NOTES: (1) if startPtr is pointing to a non-break character,
- that's fine; just return it in nbPtr
- (2) a 0-length text is passed into this routine with
- endPtr = startPtr - 1; in this case the routine will
- return endPtr + 1 ( = startPtr), since it can't find
- a non-break character among the 0 characters available for
- scanning
- }
- BEGIN
- nbPtr := startPtr;
- WHILE ORD(nbPtr) <> ORD(endPtr) + 1 DO
- BEGIN
- IF (nbPtr^ <> asciiSpace) & (nbPtr^ <> asciiCR) THEN EXIT(ScanToNonBreak); { found it }
- nbPtr := Ptr(ORD(nbPtr) + 1); { didn't find it, try next }
- END;
- END; { ScanToNonBreak }
-
- {$S QuillNew}
- PROCEDURE SelectTextToken(theTextToken: TextToken);
- { select the text represented by a token
- INPUTS: theTextToken the text token . . .
- OUTPUTS: none
- NOTES: **CHECK - switch over to this routine throughout code
- }
- BEGIN
- WITH theTextToken DO
- TESetSelect(tokenOffset,tokenOffset + tokenLength,DocumentPeek(tokenWndw)^.docTE);
- END; { SelectTextToken }
-
-
-
-
- {$S QuillNew }
- PROCEDURE SendAEClose(window: WindowPtr; saveFlag, fileParamFlag: BOOLEAN;
- fileSpec: FSSpec);
- { send an AppleEvent Close Event to myself, using the options and parameters
- specified. We'll bundle up the window as an object by index
- INPUTS: window window to be closed
- saveFlag TRUE if window should be saved first, FALSE o.w.
- fileParamFlag TRUE if we're sending along a specific file spec
- to save the window to, FALSE o.w. (if FALSE, the
- Close event handler will use the file in the window
- doc record or, if there isn't one, will concoct its
- own). Ignored is saveFlag is FALSE
- fileSpec spec for file to save to. Ignored if either saveFlag
- or fileParamFlag is FALSE
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- LABEL 9;
- VAR index: INTEGER;
- wndwObjSpec: AEDesc;
- myAppleEvent: AppleEvent;
- saveOpt: DescType;
- defReply: AppleEvent;
- BEGIN
- InitSomeDescs(@wndwObjSpec,@myAppleEvent,NIL,NIL,NIL);
- { currently we're not using defReply, so we won't init it }
-
- { make the window object }
- index := IndexFromWndwPtr(window);
- IF CheckErr( MakeObjSpecFromIndex(cDocument,gNullDesc,index,wndwObjSpec) , 6313 )
- THEN GOTO 9; { finish up }
-
- { create event }
- IF CheckErr( AECreateAppleEvent(kAECoreSuite,kAEClose,gSelfAddrDesc,kAutoGenerateReturnID,kAnyTransactionID,myAppleEvent) ,
- 6314 ) THEN GOTO 9;
-
- { add window object to event }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyDirectObject,wndwObjSpec) , 6315 ) THEN GOTO 9;
-
- { add optional save param to event - we'll always include it }
- IF saveFlag THEN saveOpt := kAEYes ELSE saveOpt := kAENo;
- IF CheckErr( AEPutParamPtr(myAppleEvent,keyAESaveOptions,typeEnumerated,@saveOpt,SizeOf(saveOpt)) ,
- 6316 ) THEN GOTO 9;
-
- { see if we need to add the optional file param }
- IF fileParamFlag THEN
- IF CheckErr( AEPutParamPtr(myAppleEvent,keyAEDestination,typeFSS,@fileSpec,SizeOf(fileSpec)) ,
- 6317 ) THEN GOTO 9;
-
- { send the event }
- IF CheckErr( AESend(myAppleEvent,defReply,kAENoReply+kAECanInteract,kAENormalPriority,kAEDefaultTimeOut,NIL,NIL) ,
- 6318 ) THEN GOTO 9;
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@wndwObjSpec,@myAppleEvent,NIL,NIL,NIL) , 6319 );
- END; { SendAEClose }
-
- {$S QuillNew}
- PROCEDURE SendAEOpenDoc(myFSSpec: FSSpec);
- { send the OpenDocs AppleEvent to myself, with a one-element list
- containing the given file spec
- INPUTS: myFSSpec file spec for file to be opened
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- NOTES: the core AEOpenDocs event is defined as taking a list of
- aliases (not file specs) as its direct parameter. However,
- we can send the file spec instead and depend on AppleEvents'
- automatic coercion. In fact, we don't really even have to put
- in a list; AppleEvents will coerce a descriptor into a 1-element
- list if called for. In this routine, though, we'll make the
- list for demonstration purposes.
- }
- LABEL 9;
- VAR myAppleEvent: AppleEvent;
- defReply: AppleEvent;
- docList: AEDescList;
- BEGIN
- InitSomeDescs(@myAppleEvent,@defReply,@docList,NIL,NIL);
-
- { step 1: create empty list }
- IF CheckErr( AECreateList(NIL,0,FALSE,docList) , 814 ) THEN EXIT(SendAEOpenDoc);
-
- { step 2: add file spec to list }
- IF CheckErr( AEPutPtr(docList,1,typeFSS,@myFSSpec,SizeOf(myFSSpec)) , 815 ) THEN GOTO 9; { finish up }
-
- { step 3: create event }
- IF CheckErr( AECreateAppleEvent(kCoreEventClass,kAEOpenDocuments,gSelfAddrDesc,kAutoGenerateReturnID,kAnyTransactionID,myAppleEvent) ,
- 816 ) THEN GOTO 9;
-
- { step 4: add list to event }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyDirectObject,docList) , 817 ) THEN GOTO 9;
-
- { step 5: send event }
- gTempBool := CheckErr( AESend(myAppleEvent,defReply,kAENoReply+kAEAlwaysInteract,kAENormalPriority,kAEDefaultTimeOut,NIL,NIL) ,
- 818 );
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@myAppleEvent,@defReply,@docList,NIL,NIL) , 819 );
- END; { SendAEOpenDoc }
-
- {$S QuillNew}
- PROCEDURE SendAEPrintDoc(docDesc: AEDesc; doInteract: BOOLEAN);
- { send the PrintDocs AppleEvent to myself, with a one-element list
- containing the given file spec
- INPUTS: docDesc descriptor for the document to be printed
- doInteract TRUE if print routine should bring up the
- print dialog, FALSE o.w.
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- NOTES: (1) The definition of the required AppleEvent PrintDocs
- calls for a list of aliases; our PrintDocs handler
- requests file specs or windows, which are the things
- it knows how to print. We can depend on coercion
- handlers (built-in and/or ours) to coerce aliases
- to files, objects to windows, etc., if possible.
- In fact, we don't really even have to put the descriptor
- in a list; AppleEvents will coerce a descriptor into a
- 1-element list if called for. In this routine, though,
- we'll make the list for demonstration purposes.
- (2) clearly this should be combined with SendAEOpenDoc; they're
- almost exactly the same
- }
-
- LABEL 7,8;
- VAR myAppleEvent: AppleEvent;
- defReply: AppleEvent;
- docList: AEDescList;
- mySendMode: AESendMode;
- BEGIN
- { step 1: create empty list }
- IF CheckErr( AECreateList(NIL,0,FALSE,docList) , 1614 ) THEN EXIT(SendAEPrintDoc);
-
- { step 2: add doc desc to list }
- IF CheckErr( AEPutDesc(docList,1,docDesc) , 1615 ) THEN GOTO 8; { dispose of list }
-
- { step 3: create event }
- IF CheckErr( AECreateAppleEvent(kCoreEventClass,kAEPrintDocuments,gSelfAddrDesc,kAutoGenerateReturnID,kAnyTransactionID,myAppleEvent) ,
- 1616 ) THEN GOTO 8;
-
- { step 4: add list to event }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyDirectObject,docList) , 1617 ) THEN GOTO 7; { dispose of event, list }
-
- { step 5: send event }
-
- IF doInteract
- THEN mySendMode := kAENoReply+kAEAlwaysInteract
- ELSE mySendMode := kAENoReply+kAENeverInteract;
-
- IF CheckErr( AESend(myAppleEvent,defReply,mySendMode,kAENormalPriority,kAEDefaultTimeOut,NIL,NIL) ,
- 1618 ) THEN GOTO 7;
-
- 7: { dispose event }
- gTempBool := CheckErr( AEDisposeDesc(myAppleEvent) , 1619 );
-
- 8: { dispose list }
- gTempBool := CheckErr( AEDisposeDesc(docList) , 1620 );
- END; { SendAEPrintDoc }
-
- {$S QuillNew}
- PROCEDURE SendAEQuit(saveOpt: DescType);
- { send a QuitEvent to myself
- INPUTS: saveOpt value for optional save parameter (we'll always send it):
- kAEYes (save dirty windows, don't ask user), kAENo (don't
- save any dirty windows), or kAEAsk (ask user on each
- dirty window)
- OUTPUTS: none
- SIDE EFFECTS:
- NOTES:
- }
- LABEL 9;
- VAR myAppleEvent: AppleEvent;
- defReply: AppleEvent;
- BEGIN
- { create event }
- IF CheckErr( AECreateAppleEvent(kCoreEventClass,kAEQuitApplication,gSelfAddrDesc,kAutoGenerateReturnID,kAnyTransactionID,myAppleEvent) , 1114)
- THEN EXIT(SendAEQuit);
-
- { add parameter }
- IF CheckErr( AEPutParamPtr(myAppleEvent,keyAESaveOptions,typeEnumerated,@saveOpt,SizeOf(saveOpt)) ,
- 1117 ) THEN GOTO 9;
-
- { send event }
- gTempBool := CheckErr( AESend(myAppleEvent,defReply,kAENoReply+kAEAlwaysInteract,kAENormalPriority,kAEDefaultTimeOut,NIL,NIL) , 1115 );
-
- 9: { dispose event }
- gTempBool := CheckErr( AEDisposeDesc(myAppleEvent) , 1116 );
- END; { SendAEQuit }
-
- {$S QuillNew }
- PROCEDURE SendAESave(window: WindowPtr; fileParamFlag: BOOLEAN;
- fileSpec: FSSpec);
- { send an AppleEvent Save Event to myself, optionally including
- a file spec. We'll bundle up the window as an object by index.
- INPUTS: window ptr to window to be save
- fileParamFlag TRUE if file parameter is being supplied;
- FALSE o.w.
- fileSpec file to save to; ignored if fileParamSpec is FALSE
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- LABEL 9;
- VAR index: INTEGER;
- wndwObjSpec: AEDesc;
- myAppleEvent: AppleEvent;
- defReply: AppleEvent;
- BEGIN
- InitSomeDescs(@wndwObjSpec,@myAppleEvent,NIL,NIL,NIL); { not using defReply this time around }
-
- { make the window object }
- index := IndexFromWndwPtr(window);
- IF CheckErr( MakeObjSpecFromIndex(cDocument,gNullDesc,index,wndwObjSpec) , 6913 )
- THEN GOTO 9; { finish up }
-
- { create event }
- IF CheckErr( AECreateAppleEvent(kAECoreSuite,kAESave,gSelfAddrDesc,kAutoGenerateReturnID,kAnyTransactionID,myAppleEvent) ,
- 6914 ) THEN GOTO 9;
-
- { add window object to event }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyDirectObject,wndwObjSpec) , 6915 ) THEN GOTO 9;
-
- { add optional file param if we need to }
- IF fileParamFlag THEN
- IF CheckErr( AEPutParamPtr(myAppleEvent,keyAEDestination,typeFSS,@fileSpec,SizeOf(fileSpec)) ,
- 6916 ) THEN GOTO 9;
-
- { send the event }
- gTempBool := CheckErr( AESend(myAppleEvent,defReply,kAENoReply+kAECanInteract,kAENormalPriority,kAEDefaultTimeOut,NIL,NIL) ,
- 6917 );
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@wndwObjSpec,@myAppleEvent,NIL,NIL,NIL) , 6918 );
- END; { SendAESave }
-
- {$S QuillNew }
- PROCEDURE SendAESetObjProp(theObj: AEDesc; theProp: DescType; theData: AEDesc);
- { send the AppleEvent to set a given property of a given object to some value.
- INPUTS: theObj the object specifier (a desc, typeObjectSpecifier)
- theProp prop to be set
- theData value to set it to (a desc)
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- LABEL 8;
- VAR propObjSpec: AEDesc;
- myAppleEvent: AppleEvent;
- defReply: AppleEvent;
- BEGIN
- { create an object spec that represents the property of the given object }
- IF CheckErr( MakePropObjSpec(theObj,theProp,propObjSpec) , 5114 )
- THEN EXIT(SendAESetObjProp); { dispose of addrDesc }
-
- { create event }
- IF CheckErr( AECreateAppleEvent(kAECoreSuite,kAESetData,gSelfAddrDesc,kAutoGenerateReturnID,kAnyTransactionID,myAppleEvent) ,
- 5115 ) THEN GOTO 8; { dispose of propObjSpec }
-
- { add prop obj spec to the event }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyDirectObject,propObjSpec) , 5116 ) THEN GOTO 8;
-
- { add prop data to the event }
- IF CheckErr( AEPutParamDesc(myAppleEvent,keyAEData,theData) , 5117 ) THEN GOTO 8;
-
- { send event }
- gTempBool := CheckErr( AESend(myAppleEvent,defReply,kAENoReply+kAEAlwaysInteract,kAENormalPriority,kAEDefaultTimeOut,NIL,NIL) , 5118 );
-
- { dispose of event } { **CHECK - anything else - like defReply? }
- gTempLong := AEDisposeDesc(myAppleEvent);
-
- 8: { dispose of propObjSepc }
- gTempLong := AEDisposeDesc(propObjSpec);
- END; { SendAESetObjProp }
-
- {$S QuillNew }
- PROCEDURE SendAESetWndwPos(index: INTEGER; thePos: Point);
- { send the AppleEvent to set the position of a given window
- to a given rectangle. The window is specified by
- index (front-to-back ordering). Position, here, is
- the top left corner of the structure region.
- INPUTS: index window index
- thePos point to set the position to
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- LABEL 8;
- VAR windowObjSpec: AEDesc;
- posDesc: AEDesc;
- BEGIN
- { turn window into an object spec desc }
- IF CheckErr( MakeObjSpecFromIndex(cDocument,gNullDesc,index,windowObjSpec) , 5313 )
- THEN EXIT(SendAESetWndwPos);
-
- { turn thePos into a desc }
- IF CheckErr( AECreateDesc(typeQDPoint,@thePos,SizeOf(thePos),posDesc) , 5314 )
- THEN GOTO 8; { dispose of windowObjSpec }
-
- SendAESetObjProp(windowObjSpec,pPosition,posDesc);
-
- { dispose of rectDesc }
- gTempLong := AEDisposeDesc(posDesc);
-
- 8: { dispose of windowObjSpec }
- gTempLong := AEDisposeDesc(windowObjSpec);
- END; { SendAESetWndwPos }
-
- {$S QuillNew }
- PROCEDURE SendAESetWndwRect(index: INTEGER; theRect: Rect);
- { send the AppleEvent to set the rect of a given window
- to a given rectangle. The window is specified by
- index (front-to-back ordering). The rect of a window,
- here, means the rect of its structure region.
- INPUTS: index window index
- theRect rect to set it to
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS:
- }
- LABEL 8;
- VAR windowObjSpec: AEDesc;
- rectDesc: AEDesc;
- BEGIN
- { turn window into an object spec desc }
- IF CheckErr( MakeObjSpecFromIndex(cDocument,gNullDesc,index,windowObjSpec) , 5013 )
- THEN EXIT(SendAESetWndwRect);
-
- { turn rect into a desc }
- IF CheckErr( AECreateDesc(typeQDRectangle,@theRect,SizeOf(theRect),rectDesc) , 5014 )
- THEN GOTO 8; { dispose of windowObjSpec }
-
- SendAESetObjProp(windowObjSpec,pBounds,rectDesc);
-
- { dispose of rectDesc }
- gTempLong := AEDisposeDesc(rectDesc);
-
- 8: { dispose of windowObjSpec }
- gTempLong := AEDisposeDesc(windowObjSpec);
- END; { SendAESetWndwRect }
-
- {$S QuillNew}
- FUNCTION SetDataForAppProp(appPropDesc: AEDesc; propDataDesc: AEDesc): OSErr;
- { given a descriptor that represents a property of the app - which
- should be of, or coerceible to, typeMyAppProp - and a descriptor
- containing data that the prop could resonably be set to, set the
- app property to that data
- INPUTS: appPropDesc a descriptor representing the app property;
- must be of, or coercible to, typeMyAppProp
- propDataDesc a descriptor containing data to set the property to
- OUTPUTS: error code (noErr if none)
- NOTES:
- 09/17/91 BHM formerly SetPropForApp
- 09/17/91 BHM now uses GetSingularData (so propDataDesc can be an object)
- 02/17/92 BHM added pUserSelction
- }
- LABEL 9;
- VAR myErr: OSErr;
- myAppProp: DescType;
- window: WindowPtr;
- myToken: TextToken;
- newDesc: AEDesc;
- myErrMode: DescType;
- BEGIN
- myErr := genericErr;
- newDesc := gNullDesc;
-
- { which prop? }
- IF CatchErr( MyAECoerceDescPtr(appPropDesc,typeMyAppProp,@myAppProp,
- SizeOf(myAppProp),gActSize) , 18313 , myErr ) THEN GOTO 9;
-
- IF myAppProp = pUserSelection THEN
- BEGIN
- { get the user selection as a text token, if possible }
- window := FrontWindow;
- IF window = NIL THEN
- BEGIN
- gTempBool := CatchErr( errAENoUserSelection , 18314 , myErr );
- GOTO 9;
- END;
-
- { make the token }
- MakeSelTextToken(window,myToken);
-
- { make a descriptor out of it, just for convenience }
- { **CHECK - the convenience has to do with the arguments of the existing }
- { SetStylTextData - but that's not a GOOD reason for this wasted effort }
- IF CatchErr( AECreateDesc(typeMyText,@myToken,SizeOf(myToken),newDesc) , 18315 , myErr )
- THEN GOTO 9;
-
- { and set the data for it }
- gTempBool := CatchErr( SetStylTextData(newDesc,propDataDesc) , 18316 , myErr );
- GOTO 9;
- END; { pUserSelection }
-
- IF myAppProp = pErrMode THEN
- BEGIN
- { what data? }
- IF CatchErr( GetSingularData(propDataDesc,typeEnumerated,newDesc) , 18317 , myErr )
- THEN GOTO 9;
- IF CatchErr( MyAECoerceDescPtr(newDesc,typeEnumerated,@myErrMode,SizeOf(myErrMode),gActSize) ,
- 18318 , myErr ) THEN GOTO 9; { we COULD go directly into the handle here }
-
- myErr := noErr; { assume for 2 lines }
- IF myErrMode = kShowAllErrs THEN gShowAllErrs := TRUE
- ELSE IF myErrMode = kShowFewErrs THEN gShowAllErrs := FALSE
- ELSE gTempBool := CatchErr( errAEWrongDataType , 18319 , myErr );
-
- GOTO 9;
- END; { pErrMode }
-
- { if we get to here, it's a prop we've never heard of }
- gTempBool := CatchErr( errAEWrongDataType , 18320 , myErr );
-
- 9: { finish up }
-
- gTempBool := CheckErr( AEDisposeDesc(newDesc) , 18321 );
-
- SetDataForAppProp := myErr;
- END; { SetDataForAppProp }
-
-
- {$S QuillNew}
- FUNCTION SetDataForTextProp(textPropDesc: AEDesc; propDataDesc: AEDesc): OSErr;
- { given a descriptor that represents a property of a window - which
- should be of, or coercible to, typeMyTextProp - and a descriptor
- containing data that the prop could reasonably be set to, set the
- text property to that data.
- INPUTS: textPropDesc a descriptor representing the property
- of some text. Must be of, or coercible
- to, typeMyTextProp.
- propDataDesc a descriptor containing data to set the property to
- OUTPUTS: error code (noErr if none)
- NOTES: we may want to break this one up differently later (in particular,
- the style stuff has gotten more complicated, and should be broken out)
- 08/01/91 BHM For styles, threw in a coercion to typeAEList, so that
- we can accept a single style item (not in a list)
- (the coercion routine itself is built in to AE Mngr)
- 09/17/91 BHM Formerly SetPropForText
- 09/17/91 BHM Now uses GetSingularData, so propDataDesc can be an object
- (but have we, in some cases, lost one level of coercion - **CHECK)
- }
- LABEL 9;
- VAR myErr: OSErr;
- myTextProp: TextPropToken;
- myProp: DescType;
- newDesc: AEDesc;
- newSize: INTEGER;
- newStyle: TextStyle;
- mode: INTEGER;
- nameDesc: AEDesc;
- nameStr: Str255;
- actSize: LongInt;
- fontNum: INTEGER;
- wndwTE: TEHandle;
- onStyles: Style;
- offStyles: Style;
- onStylesNotNull: BOOLEAN;
- styleDesc: AEDescList;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@nameDesc,@styleDesc,@newDesc,NIL,NIL);
-
- IF CatchErr( MyAECoerceDescPtr(textPropDesc,typeMyTextProp,@myTextProp,SizeOf(myTextProp),
- gActSize) , 16413 , myErr ) THEN GOTO 9;
-
- myProp := myTextProp.tpProp;
-
- IF myProp = pPointSize THEN
- BEGIN
- IF CatchErr( GetSingularData(propDataDesc,typeShortInteger,newDesc) , 16421 , myErr )
- THEN GOTO 9;
- IF CatchErr( MyAECoerceDescPtr(propDataDesc,typeShortInteger,@newSize,SizeOf(newSize),
- gActSize) , 16414 , myErr ) THEN GOTO 9;
- { we could skip the above step and go directly into the handle for the next }
- newStyle.tsSize := newSize;
- mode := doSize;
- END { set-up for pPointSize }
-
- ELSE IF myProp = pFont THEN
- BEGIN
- IF CatchErr( GetSingularData(propDataDesc,typeChar,nameDesc) , 16419 , myErr ) THEN GOTO 9;
- IF CatchErr( TextDescToStr(nameDesc,nameStr,actSize) , 16420 , myErr ) THEN GOTO 9;
-
- IF actSize > 255 THEN
- BEGIN
- { font name illegally long }
- gTempBool := CatchErr( errAEBadData , 16421 , myErr );
- GOTO 9;
- END;
-
- GetFNum(nameStr,fontNum);
-
- newStyle.tsFont := fontNum;
- mode := doFont;
- END { set-up for pFont }
-
- ELSE IF myProp = pTextStyles THEN
- BEGIN
- IF CatchErr( GetSingularData(propDataDesc,typeTextStyles,styleDesc) , 16417 , myErr ) THEN GOTO 9;
- IF CatchErr( StyleDescToStyleSets(styleDesc,onStyles,offStyles,TRUE) , 16416 , myErr )
- THEN GOTO 9;
- END { set-up for pTextStyles }
-
- ELSE
- BEGIN
- { not a property we can handle }
- myErr := errAEWrongDataType;
- GOTO 9;
- END;
-
- { we have a prop to set }
- { first, select text }
- WITH myTextProp.tpText DO
- BEGIN
- wndwTE := DocumentPeek(tokenWndw)^.docTE;
- TESetSelect(tokenOffset,tokenOffset + tokenLength,wndwTE);
- END;
-
- { and set the new value }
- { for now, we have to special-case face, because we have "on" and "off" }
-
- IF myProp = pTextStyles THEN
- BEGIN
- { **CHECK - on doToggle with plain, and note #131 }
- { to turn off the offStyles, without affecting the others,
- we use the following scheme:
- (1) turn them all ON
- (2) use doToggle to turn them OFF
- doToggle doesn't work right with Plain, and anyway in the
- offStyles = Plain case we don't really have to do anything
- with the offStyles, so we'll skip it
- }
- onStylesNotNull := (onStyles <> []); { handy later }
-
- IF offStyles <> [] THEN
- BEGIN
- { offStyles not empty }
- { so, first, "turn the offs ON" }
- newStyle.tsFace := offStyles;
- TESetStyle(doFace,newStyle,FALSE,wndwTE); { don't redraw }
- { now turn them off, using doToggle }
- TESetStyle(doFace + doToggle,newStyle,(NOT onStylesNotNull),wndwTE); { redraw only if onStyles null, i.e., no more style changes }
- END; { of offStyles not empty }
-
- { now turn ON the on's - EXCEPT: if onStyles is empty,
- we don't want to make the call to TESetStyle, because
- that would set the style to Plain (i.e., turn everything
- off)
- }
- IF onStylesNotNull THEN
- BEGIN
- newStyle.tsFace := onStyles;
- TESetStyle(doFace,newStyle,TRUE,wndwTE); { ok, redraw }
- END;
-
- END { of pTextStyles }
-
- ELSE TESetStyle(mode,newStyle,TRUE,wndwTE); { this is for props other than pTextStyles, so far }
-
- DirtyWindow(myTextProp.tpText.tokenWndw);
- myErr := noErr;
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@nameDesc,@styleDesc,@newDesc,NIL,NIL) , 16418 );
-
- SetDataForTextProp := myErr;
- END; { SetDataForTextProp }
-
-
- {$S QuillNew2}
- FUNCTION SetDataForToken(myToken: AEDesc; dataDesc: AEDesc): OSErr;
- { given one of my private tokens, set it to the given data. The data
- can either be raw (a data descriptor), or an object - however, for now
- at least, it can't be an object that resolves to a list.
-
- This routine only takes tokens (for myToken), not objects or lists.
-
- INPUTS: myToken token representing the thing whose data is to be set
- dataDesc descriptor containing the data (either raw or as an object)
- OUTPUTS: error code (noErr if none)
-
- **CHECK - QUESTION - should we pry the tokens out of their descriptors here, or leave
- that for further down? (for now, we'll push it further down)
- (also note IF-THEN-ELSE structure, which may be useful in similar routines. What I
- really want is a CASE on types!)
- (ALSO note: without the "paper-trail" CatchErr calls, this could all be in "SetDataForToken := . . ."
- form)
- }
- VAR myErr: OSErr;
- myType: DescType;
- BEGIN
- myErr := genericErr;
-
- myType := myToken.descriptorType;
-
- IF myType = typeMyWndwProp THEN
- gTempBool := CatchErr( SetDataForWndwProp(myToken,dataDesc) , 20813 , myErr ) { like old SetPropForWndwDesc }
-
- ELSE IF myType = typeMyText THEN
- gTempBool := CatchErr( SetStylTextData(myToken,dataDesc) , 20814 , myErr )
-
- ELSE IF myType = typeMyTextProp THEN
- gTempBool := CatchErr( SetDataForTextProp(myToken,dataDesc) , 20815 , myErr ) { old SetPropForText }
-
- ELSE IF myType = typeMyAppProp THEN
- gTempBool := CatchErr( SetDataForAppProp(myToken,dataDesc) , 20816 , myErr ) { old SetPropForApp }
-
- ELSE myErr := errAEWrongDataType; { nothing we know how to set the data of }
-
- SetDataForToken := myErr;
- END; { SetDataForToken }
-
- {$S QuillNew2}
- FUNCTION SetDataForTokenList(myList: AEDesc; dataDesc: AEDesc): OSErr;
- { this routine takes a "token list" and sets the data for each token in
- it to a given value. The elements of the token list may themselves be
- lists or tokens, but the ultimate "node elements" of the list have to be
- tokens.
-
- The data supplied may either be raw data or an object specifier that
- resolves to a single object; it may not resolve to a list. For now.
-
- INPUTS: myList the "token list"
- dataDesc data descriptor; may be raw data or an object (but the
- object may not resolve to a list)
- OUTPUTS: error code (noErr if none)
- NOTES: (1) it would actually be very powerful to allow dataDesc to be a list
- (possibly with a special typeDataList, to distinguish it from data values
- that happen to be lists all by themselves) with the same list structure
- as myList, and set values on a 1-by-1 basis. Future direction.
- (2) right now dataDesc gets resolved (if it's an object) and/or
- coerced to the right data type once for each element in myList, because
- we don't know what type's needed until we get to the individual elements.
- For homogeneous lists - like the ones returned by the OSL - this seems
- like a lot of extra effort, and should be optimized. Future direction.
- }
- LABEL 9;
- VAR myErr: OSErr;
- itemCount: LongInt;
- i: LongInt;
- thisItem: AEDesc;
- BEGIN
- myErr := genericErr;
- thisItem := gNullDesc;
-
- { count the items }
- IF CatchErr( AECountItems(myList,itemCount) , 20913 , myErr ) THEN GOTO 9;
-
- IF itemCount = 0 THEN GOTO 9;
-
- { since we're setting data, go backwards through the list to avoid side effects }
- FOR i := itemCount DOWNTO 1 DO
- BEGIN
- { get the item }
- IF CatchErr( AEGetNthDesc(myList,i,typeWildCard,gReturnedKeywd,thisItem) , 20914 ,
- myErr ) THEN GOTO 9;
-
- { if it's a list, call myself recursively }
- IF thisItem.descriptorType = typeAEList THEN
- BEGIN
- IF CatchErr( SetDataForTokenList(thisItem,dataDesc) , 20915 , myErr )
- THEN GOTO 9;
- END
- ELSE
- BEGIN
- { otherwise assume it's a token }
- IF CatchErr( SetDataForToken(thisItem,dataDesc) , 20916 , myErr )
- THEN GOTO 9;
- END;
-
- { dispose of this item }
- gTempBool := CheckErr( AEDisposeDesc(thisItem) , 20917 );
- thisItem := gNullDesc; { just for neatness }
- END; { of FOR loop }
-
- 9: { finish up }
-
- gTempBool := CheckErr( AEDisposeDesc(thisItem) , 20918 );
-
- SetDataForTokenList := myErr;
- END; { SetDataForTokenList }
-
- {$S QuillNew}
- FUNCTION SetDataForWndwProp(wndwPropDesc: AEDesc; propDataDesc: AEDesc): OSErr;
- { given a descriptor which represents a property of a window - and should
- be of, or coercible to, typeMyWndwProp - and a descriptor containing data
- that the prop could reasonably be set to - set the window property
- to that data.
- INPUTS: wndwPropDesc a descriptor representing a property of a window.
- Must be of, or coercible to, typeMyWndwProp.
- propDataDesc a descriptor containing data to set the property to
- OUTPUTS: error code (noErr if none)
- NOTES: this routine actually just grabs the window prop token out of its
- descriptor and calls SetWindowProp
- 09/17/91 BHM formerly SetPropForWndwDesc
- }
- LABEL 9;
- VAR myErr: OSErr;
- myWndwProp: WndwPropToken;
- BEGIN
- myErr := genericErr; { or whatever }
-
- IF CatchErr( MyAECoerceDescPtr(wndwPropDesc,typeMyWndwProp,@myWndwProp,
- SizeOf(myWndwProp),gActSize) , 15213 , myErr ) THEN GOTO 9;
-
- WITH myWndwProp DO
- BEGIN
- IF CatchErr( SetWindowProp(wpWndw,wpProp,propDataDesc) , 15214 ,
- myErr ) THEN GOTO 9;
- END;
-
- 9: { finish up }
- SetDataForWndwProp := myErr;
- END; { SetDataForWndwProp }
-
-
- {$S QuillNew}
- PROCEDURE SetFontForSelText(window: WindowPtr; fontName: Str255);
- { concoct an object for the selected text in the given window,
- and send a Set Data event to change the font of that text to
- the given font.
- INPUT: window ptr to the window
- fontName name of the font
- OUTPUTS: none
- NOTES: the routine will complain (with CheckErr) if it
- encounters any errors, but it will not pass those
- errors on up to the calling function
- }
- LABEL 9;
- VAR selText: AEDesc;
- nameDesc: AEDesc;
- BEGIN
- InitSomeDescs(@selText,@nameDesc,NIL,NIL,NIL);
-
- { make an object representing the selected text }
- IF CheckErr( SmartMakeSelTextObj(window,selText) , 16713 ) THEN GOTO 9;
-
- { make a text descriptor for the font name }
- IF CheckErr( StrToTextDesc(fontName,nameDesc) , 16714 ) THEN GOTO 9;
-
- { now send the Set Data event to set this prop }
- SendAESetObjProp(selText,pFont,nameDesc);
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@selText,@nameDesc,NIL,NIL,NIL) , 16715 );
- END; { SetFontForSelText }
-
-
-
-
- {$S QuillNew}
- PROCEDURE SetSizeForSelText(window: WindowPtr; newSize: INTEGER);
- { concoct an object for the selected text in the given window,
- and send a Set Data event to change the size of that text to
- the given size.
- INPUT: window ptr to the window
- newSize new size for the text
- OUTPUTS: none
- NOTES: the routine will complain (with CheckErr) if it
- encounters any errors, but it will not pass those
- errors on up to the calling function
- }
- LABEL 9;
- VAR selText: AEDesc;
- sizeDesc: AEDesc;
- BEGIN
- InitSomeDescs(@selText,@sizeDesc,NIL,NIL,NIL);
-
- { make an object representing the selected text }
- IF CheckErr( SmartMakeSelTextObj(window,selText) , 16813 ) THEN GOTO 9;
-
- { make a descriptor for the new size }
- IF CheckErr( AECreateDesc(typeShortInteger,@newSize,SizeOf(newSize),sizeDesc) , 16814 ) THEN GOTO 9;
-
- { now send the Set Data event to set this prop }
- SendAESetObjProp(selText,pPointSize,sizeDesc);
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@selText,@sizeDesc,NIL,NIL,NIL) , 16815 );
- END; { SetSizeForSelText }
-
-
- {$S QuillNew}
- FUNCTION SetStyleForSelText(window: WindowPtr; onStyles: Style;
- offStyles: Style): OSErr;
- { concoct an object for the selected text in the given window, and send a
- Set Data event to change the style of that text to the given values.
- We provide one set of style items to be turned uniformly ON in the text,
- and one set to be turned uniformly OFF. Any style item not present in
- either set should be left alone. If a style item is in both sets, that's
- an error (errAEBadData)
- INPUTS: window ptr to the window
- onStyles set of style items to be turned ON
- offStyles set of style items to be turned OFF
- OUTPUTS: error code (noErr if none)
- NOTES: the call to StyleSetToList will report the "style item
- in both sets" err, so we don't need to check for it
- explicitly here
- ( **CHECK - we might want to make this more similar to
- SetSizeForSelText, SetFontForSelText, in terms of error-
- reporting behavior)
- }
- LABEL 9;
- VAR myErr: OSErr;
- selText: AEDesc;
- styleData: AEDesc;
- count: LongInt;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@selText,@styleData,NIL,NIL,NIL);
-
- { make an object for the selected text }
- IF CatchErr( SmartMakeSelTextObj(window,selText) , 16913 , myErr ) THEN GOTO 9;
-
- { make a typeTextStyles desc out of the styles }
-
- { **CHECK - should we special-case 1-item deals to record better? }
- { or more generally, if offStyles = [] . . . . }
-
- IF CatchErr( SmartMakeStyleData(onStyles,offStyles,styleData) , 16914 , myErr )
- THEN GOTO 9;
-
- { send the Set Data event }
- SendAESetObjProp(selText,pTextStyles,styleData);
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@selText,@styleData,NIL,NIL,NIL) , 16915 );
-
- SetStyleForSelText := myErr;
- END; { SetStyleForSelText }
-
- {$S QuillNew}
- FUNCTION SetStylTextData(textDesc: AEDesc; dataDesc: AEDesc): OSErr;
- { given a text descriptor (which must be of, or coercible to, typeMyText)
- and some text data (which must be of, or coercible to, either typeChar
- or typeStyledText), set that text to that text data
- INPUTS: textDesc descriptor for the text object. Must be
- of, or coercible to, typeMyText
- dataDesc descriptor for the data to set the text
- object to. Must be of, or coercible to,
- either typeChar or typeStyledText
- OUTPUTS: error code (noErr if none)
- NOTES: right now we have a CoerceStylTextToText, but no
- CoerceTextToStylText. For this reason we check for
- typeStyledText first. I handle the two cases separately.
- In the future it may be better to coerce text to
- stylText, and have no special cases here, but I'm
- not comfortable with that yet.
- ALSO: we may want to break this up into the part
- that makes descriptors into values, and the part
- that actually handles the text.
- 09/17/91 BHM now uses GetSingularData (so dataDesc can be typeObjectSpecifier)
- }
- LABEL 9;
- VAR myErr: OSErr;
- stylHandle: Handle;
- myText: TextToken;
- newDesc: AEDesc;
- textData: AEDesc;
- stylData: AEDesc;
- textHndl: Handle;
- wndwTE: TEHandle;
- BEGIN
- myErr := genericErr; { or whatever }
- stylHandle := NIL;
- InitSomeDescs(@newDesc,@textData,@stylData,NIL,NIL);
-
- IF CatchErr( MyAECoerceDescPtr(textDesc,typeMyText,@myText,SizeOf(myText),gActSize) ,
- 15313 , myErr ) THEN GOTO 9;
-
- { try to pick up data as typeStyledText }
- IF QuietGetSingularData(dataDesc,typeStyledText,newDesc) = noErr THEN
- BEGIN
- { got typeStyledText - now make it an AERecord }
- IF CatchErr( MyAEChangeDescType(newDesc,typeAERecord) , 15314 , myErr )
- THEN GOTO 9; { **CHECK MyAEChangeDescType }
-
- { get the text out of it }
- IF CatchErr( AEGetKeyDesc(newDesc,keyAEText,typeChar,textData) , 15315 , myErr )
- THEN GOTO 9;
-
- { get the style info out }
- IF CatchErr( AEGetKeyDesc(newDesc,keyAEStyles,typeScrapStyles,stylData) ,
- 15316 , myErr ) THEN GOTO 9;
-
- stylHandle := stylData.dataHandle;
- IF GetHandleSize(stylHandle) = 0 THEN stylHandle := NIL; { seems safer somehow }
- END { of getting info out of typeStyledText }
- ELSE
- BEGIN
- { didn't get typeStyledText; try typeChar }
- IF QuietGetSingularData(dataDesc,typeChar,textData) <> noErr THEN
- BEGIN
- { didn't get either }
- myErr := errAEWrongDataType;
- GOTO 9;
- END; { of didn't get either }
- END; { of try for typeChar }
-
- { if we get here we at least have text, and stylData is either good or NIL }
- textHndl := textData.dataHandle; { should I **CHECK for 0 chars? }
-
- HLock(textHndl);
-
- { select text represented by myText }
- WITH myText DO
- BEGIN
- wndwTE := DocumentPeek(tokenWndw)^.docTE;
- TESetSelect(tokenOffset,tokenOffset + tokenLength,wndwTE);
- END;
-
- { delete existing chars }
- TEDelete(wndwTE);
-
- { put in new chars, possibly with style info }
- TEStylInsert(textHndl^,GetHandleSize(textHndl),StScrpHandle(stylHandle),wndwTE);
-
- HUnlock(textHndl);
-
- { everything looks good }
- DirtyWindow(myText.tokenWndw);
- myErr := noErr;
-
- 9: { finish up }
-
- gTempBool := CheckErr(DisposeSomeDescs(@newDesc,@textData,@stylData,NIL,NIL) , 15317 );
-
- SetStylTextData := myErr;
- END; { SetStylTextData }
-
- {$S QuillNew}
- FUNCTION SetUpEdit(theAppleEvent: AppleEvent; VAR window: WindowPtr): OSErr;
- { this is the common code for the Cut, Copy, Paste, and Clear
- events. It gets the direct object out of the Apple Event as
- a text token, selects the specified text, and returns a ptr to
- the window the text is in. If there is no direct object, we
- default to the current selection; SetUpEdit returns a ptr to
- the front window (if there isn't any, that's an error). If
- there is a direct object, but we can't get a text token from it,
- that's an error too.
- INPUTS: theAppleEvent the apple event
- window return VAR for the window the text is in
- OUTPUTS: error code (noErr if none)
- NOTES:
- 02/20/92 BHM Changed to resolve dir obj here (and to reject lists)
- }
- LABEL 9;
- VAR myErr: OSErr;
- paramErr: OSErr;
- myDirObj: AEDesc;
- resDesc: AEDesc;
- myTextToken: TextToken;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@myDirObj,@resDesc,NIL,NIL,NIL);
-
- { get the direct object, if any }
- paramErr := AEGetParamDesc(theAppleEvent,keyDirectObject,typeObjectSpecifier,myDirObj);
-
- { ordinarily this event has no required parameters, but }
- { it's best to check anyway (the client could add some ) }
- IF CatchErr( GotRequiredParams(theAppleEvent) , 17613 , myErr ) THEN GOTO 9;
-
- { now let's work on the direct object, if any }
- IF paramErr = errAEDescNotFound THEN
- BEGIN
- { no direct object; return current window }
- window := FrontWindow;
- IF window = NIL THEN gTempBool := CatchErr( errAENoSuchObject , 17614 , myErr )
- ELSE myErr := noErr;
- GOTO 9;
- END;
-
- IF paramErr = noErr THEN
- BEGIN
- { got a direct object; resolve it }
- IF CatchErr( AEResolve(myDirObj,kAEIDoMinimum,resDesc) , 17615 , myErr ) THEN GOTO 9;
-
- { if it's a list, that's an error for me }
- IF resDesc.descriptorType = typeAEList THEN
- BEGIN
- gTempBool := CatchErr( errAENotASingleObject , 17616 , myErr );
- GOTO 9;
- END;
-
- { it's an object; better be a text token }
- IF CatchErr( MyAECoerceDescPtr(resDesc,typeMyText,@myTextToken,SizeOf(myTextToken),gActSize) , 17617 ,
- myErr ) THEN GOTO 9;
-
- { got a text token }
- window := myTextToken.tokenWndw;
- SelectTextToken(myTextToken);
- myErr := noErr;
- GOTO 9;
- END;
-
- { if we get here, we had some other trouble with the direct parameter }
- gTempBool := CatchErr( paramErr , 17618 , myErr);
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@myDirObj,@resDesc,NIL,NIL,NIL) , 17619 );
-
- SetUpEdit := myErr;
- END; { SetUpEdit }
-
-
- {$S QuillNew }
- FUNCTION SetWindowProp(window: WindowPtr; theProp: DescType;
- propData: AEDesc): OSErr;
- { set a property of a window to some value
- INPUTS: window ptr to the window
- theProp property to be set
- propData value to set it to
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- NOTES: I would rather do this as a CASE, but there are compiler problems
- 09/17/91 BHM (1) now uses GetSingularData (so propData can be an object)
- (2) this should be rewritten and cleaned up! (**CHECK)
- 02/17/91 BHM dropped pText, which is now pContents. IMPORTANT: pContents
- does not appear in this routine because the accessor turns it
- into a text token, which is handled over in SetStylTextData.
- This is EXPERIMENTAL - **CHECK
- }
- LABEL 9;
- VAR myErr: OSErr;
- newDesc: AEDesc;
- myRect: Rect;
- actSize: Size;
- myPoint: Point;
- oldName: Str255;
- newName: Str255;
- myText: TextToken;
- BEGIN
- myErr := genericErr;
- newDesc := gNullDesc;
-
- IF theProp = pBounds THEN
- BEGIN
-
- { get the rectangle }
- IF CatchErr( GetSingularData(propData,typeQDRectangle,newDesc) , 4013 , myErr ) THEN GOTO 9;
- IF CatchErr( MyAECoerceDescPtr(newDesc,typeQDRectangle,@myRect,SizeOf(myRect),actSize) , 4014 , myErr )
- THEN GOTO 9; { COULD just go into handle }
-
- { now set the property }
- WITH myRect DO
- BEGIN
- { the rectangle is for the structure region, and is in global coordinates }
- { MoveWindow and SizeWindow apply to the content region, so we have to massage a little }
- { the massage is specific to the type of window we are using }
- top := top+19;
- left := left+1;
- bottom := bottom-2;
- right := right-2; { should we **CHECK for bad values ? }
-
- { myRect is now adjusted for the content region }
- MoveWindow(window,left,top,FALSE);
- SizeWindow(window,right-left,bottom-top,TRUE);
- END;
-
- ResizeWindow(window);
- GOTO 9;
- END; { IF pBounds }
-
- IF theProp = pPosition THEN
- BEGIN
-
- { get the point }
- IF CatchErr( GetSingularData(propData,typeQDPoint,newDesc) , 4015 , myErr ) THEN GOTO 9;
- IF CatchErr( MyAECoerceDescPtr(newDesc,typeQDPoint,@myPoint,SizeOf(myRect),actSize) , 4016 , myErr )
- THEN GOTO 9;
-
- { now set the property }
- WITH myPoint DO
- BEGIN
- { the point is for the structure region, and is in global coordinates }
- { MoveWindow applies to the content region, so we have to massage a little }
- { the massage is specific to the type of window we are using }
- v := v+19;
- h := h+1;
-
- { myPoint is now adjusted for the content region }
- MoveWindow(window,h,v,FALSE);
- END;
-
- ResizeWindow(window);
- GOTO 9;
- END; { IF pPosition }
-
- IF theProp = pName THEN
- BEGIN
-
- { get the name }
- IF CatchErr( GetSingularData(propData,typeChar,newDesc) , 4017 , myErr ) THEN GOTO 9;
- IF CatchErr( TextDescToStr(newDesc,newName,actSize) , 4018 , myErr ) THEN GOTO 9;
-
- { now set the property }
- GetWTitle(window,oldName);
- SetWTitle(window,newName);
- DirtyWindow(window);
- { if the name has really changed, mark the docFile as invalid }
- IF NOT EqualString(oldName,newName,FALSE,TRUE) { ignore case but not diacriticals }
- THEN DocumentPeek(window)^.docFile.vRefNum := badVRefNum;
-
- GOTO 9;
- END; { IF pName }
-
- { can't handle this property }
- gTempBool := CatchErr( errAEWrongDataType , 4020 , myErr );
-
- 9: { finish up }
- gTempBool := CheckErr( AEDisposeDesc(newDesc) , 4021 );
-
-
- SetWindowProp := myErr;
- END; { SetWindowProp }
-
-
- {$S QuillNew }
- PROCEDURE ShutTheWindow(window: WindowPtr);
- { this routine actually closes down the window and
- throws away all associated storage.
- INPUTS: window ptr to window
- OUTPUTS: none
- ERRORS:
- SIDE EFFECTS: decrements gNumDocuments (number of documents open)
- }
- BEGIN
- WITH DocumentPeek(window)^ DO IF docTE <> NIL THEN TEDispose(docTE);
- CloseWindow(window);
- DisposPtr(Ptr(window));
- gNumDocuments := gNumDocuments - 1;
- END; { ShutTheWindow }
-
- {$S QuillNew }
- FUNCTION SmartCloseAll(saveOpt: DescType; VAR userCancelled: BOOLEAN): OSErr;
- { this is a cover proc for CloseAllNoSave, CloseAllWithSave,
- and CloseAllAskUser. saveOpt can be kAENo (no save), kAEYes
- (with save), or kAEAsk (ask user). In the "ask user" case,
- the routine will call AEInteractWithUser when it has to interact
- (and not before!), and will also give the user a chance to cancel
- with each dialog (dialogs will only be put up in the "ask user" case,
- and even then only for dirty windows).
- INPUTS: saveOpt save/don't save/ask user
- userCancelled TRUE if user cancelled, FALSE o.w. (this
- is only meaningful in the "ask user" case,
- and will be set to FALSE for the other two.
- If the call fails, userCancelled is undefined,
- but we'll set it to FALSE then also
- OUTPUTS: error code (noErr if none). Note that the "no save" case
- can't generate an error
- ERRORS:
- SIDE EFFECTS:
- }
- BEGIN
- userCancelled := FALSE;
-
- IF saveOpt = kAENo THEN
- BEGIN
- CloseAllNoSave;
- SmartCloseAll := noErr;
- EXIT(SmartCloseAll);
- END;
-
- IF saveOpt = kAEYes THEN
- BEGIN
- SmartCloseAll := CloseAllWithSave;
- EXIT(SmartCloseAll);
- END;
-
- IF saveOpt = kAEAsk THEN
- BEGIN
- SmartCloseAll := CloseAllAskUser(userCancelled);
- EXIT(SmartCloseAll);
- END;
-
- { bad saveOpt value }
- DoMyErr(genericErr,8613);
-
- END; { SmartCloseAll }
-
- {$S QuillNew2}
- FUNCTION SmartMakeSelTextObj(window: WindowPtr; VAR selTextObj: AEDesc): OSErr;
- VAR myErr: OSErr;
- myToken: TextToken;
- BEGIN
- myErr := genericErr;
- selTextObj := gNullDesc;
-
-
- WITH DocumentPeek(window)^.docTE^^ DO
- BEGIN
- myToken.tokenOffset := selStart;
- myToken.tokenLength := selEnd - selStart;
- END;
-
- myToken.tokenWndw := window;
- myToken.tokenClass := cText;
-
- gTempBool := CatchErr( SmartTokenRep(myToken,selTextObj) , 21813 , myErr );
-
-
- SmartMakeSelTextObj := myErr;
- END; { SmartMakeSelTextObj }
-
- {$S QuillNew2}
- FUNCTION SmartMakeStyleData(onStyles: Style; offStyles: Style;
- VAR styleData: AEDesc): OSErr;
- { like StyleSetsToStyleDesc, this routine takes a collection of "on"
- styles and "off" styles and creates an AEDesc that represents the
- specified text style. However, it produces a desc that may be
- better for recording purposes. In particular, if the specified
- style is (equivalent to) Plain, we get the single enumerated value
- kAEPlain; if it's a single "on" style item (e.g., just bold), we get
- the corresponding enumerated value (kAEBold); and if, in other cases,
- offStyles is empty, then we just get a list of the "on" styles.
-
- When offStyles is not empty, and we're not in the Plain case, we get
- the "standard" typeTextStyles descriptor.
-
- The point here is to be able to record "set the style to bold" rather
- than "set the style to: typeTextStyles[on:[bold],off:[]]" (or whatever
- the syntax would be for the full typeTextStyles desc).
- INPUTS: onStyles the style items to be turned on
- offStyles the style items to be turned off
- styleData return VAR for style info desc - type will be
- either typeEnumerated, or typeAEList, or typeTextStyles
- OUTPUTS: error code (noErr if none)
- NOTES: it's important to note that HandleSetData can handle all 3 types because
- we have coercions to get from typeEnumerated and typeAEList to typeTextStyles
- }
- LABEL 9;
- VAR myErr: OSErr;
- thisVal: DescType;
- onList: AEDesc;
- itemCount: LongInt;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@styleData,@onList,NIL,NIL,NIL);
-
- { start by checking for Plain }
- IF (offStyles = gAllStyles) & (onStyles = []) THEN
- BEGIN
- { Plain case }
- thisVal := kAEPlain;
- gTempBool := CatchErr( AECreateDesc(typeEnumerated,@thisVal,SizeOf(thisVal),styleData) ,
- 22713 , myErr );
- GOTO 9;
- END;
-
- { maybe it's not even a special case }
- IF offStyles <> [] THEN
- BEGIN
- gTempBool := CatchErr( StyleSetsToStyleDesc(onStyles,offStyles,styleData,TRUE,TRUE) , 22714 , myErr);
- GOTO 9;
- END;
-
- { well, it IS a special case - make a list, then check for number of elements }
- { **CHECK - is there REALLY no way to ask Pascal how large a set is? }
-
- IF CatchErr( StyleSetToList(onStyles,onList) , 22715 , myErr ) THEN GOTO 9;
-
- { now, count the list }
- IF CatchErr( AECountItems(onList,itemCount) , 22716 , myErr ) THEN GOTO 9;
-
- { if there's exactly one element, then get it out }
- IF itemCount = 1 THEN
- BEGIN
- IF CatchErr( AEGetNthDesc(onList,1,typeEnumerated,gReturnedKeywd,styleData) ,
- 22717 , myErr ) THEN GOTO 9;
- END
- ELSE
- BEGIN
- { count <> 1; just duplicate list }
- IF CatchErr( AEDuplicateDesc(onList,styleData) , 22718 , myErr ) THEN GOTO 9;
- END;
-
- 9:
- IF myErr <> noErr THEN gTempBool := CheckErr( AEDisposeDesc(styleData) , 22719 );
-
- gTempBool := CheckErr( AEDisposeDesc(onList) , 22720 );
-
- SmartMakeStyleData := myErr;
- END; { SmartMakeStyleData }
-
- {$S QuillNew2}
- FUNCTION SmartTokenRep(myToken: TextToken; VAR smartDesc: AEDesc): OSErr;
- { this routine takes a text token and checks to see if it can be represented
- as a line, item, word, or char - or a range thereof. It checks in that
- order; note that we can always represent things as ranges of characters
- if we have to (well, except "spots").
- INPUTS: myToken token representing the text
- smartDesc object descriptor containing a "smart"
- representation of the text
- OUTPUTS: error code (noErr if none)
- NOTES: I am not AT ALL happy with this brute-force routine, but it seems
- to work; I'll get back to it.
- 02/13/92 BHM Now checks on textHndl before unlocking it (ugly bug)
- 02/14/92 BHM Fixed bug concerning words at the very beginning or end
- of a window (I was relying on possibly uninitalized pointers
- to check first and last characters)
- }
- LABEL 9;
- CONST kNoChar = 1;
- kCR = 2;
- kComma = 3;
- kSpace = 4;
- kOther = 5;
-
- VAR myErr: OSErr;
- index: LongInt;
- wndwObj: AEDesc;
- textHndl: Handle;
- textLength: LongInt;
- textPtr: Ptr;
- leftKind: INTEGER;
- leftPtr: Ptr;
- leftChar: SignedByte;
- rightPtr: Ptr;
- rightChar: SignedByte;
- rightKind: INTEGER;
- textKind: DescType;
- firstChar: SignedByte;
- lastChar: SignedByte;
- leftIndex: LongInt;
- rightIndex: LongInt;
- leftToken: TextToken;
- leftCount: LongInt;
- leftDesc: AEDesc;
- rightDesc: AEDesc;
- elemCount: LongInt;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@smartDesc,@wndwObj,@leftDesc,@rightDesc,NIL);
- textHndl := NIL;
-
- WITH myToken DO
- BEGIN
-
-
- { make an obj spec for the window }
- index := IndexFromWndwPtr(tokenWndw);
- IF index = 0 THEN
- BEGIN
- { no such window }
- gTempBool := CatchErr( errAEBadData , 21713 , myErr );
- GOTO 9;
- END;
-
- IF CatchErr( MakeObjSpecFromIndex(cDocument,gNullDesc,index,wndwObj) , 21714 , myErr )
- THEN GOTO 9;
-
- IF tokenLength = 0 THEN
- BEGIN
- { this, my friends, is a spot }
- gTempBool := CatchErr( MakeObjSpecFromIndex(cSpot,wndwObj,tokenOffset+1,smartDesc) ,
- 21715 , myErr );
- GOTO 9;
- END;
-
- { not a spot }
-
- WITH DocumentPeek(tokenWndw)^.docTE^^ DO
- BEGIN
- textHndl := hText;
- textLength := teLength;
- END;
-
-
- HLock(textHndl);
- textPtr := textHndl^; { ptr to first char IN THE WINDOW }
-
- { classify the char to the left of the token }
- IF tokenOffset = 0 THEN leftKind := kNoChar
- ELSE
- BEGIN
- leftPtr := Ptr(ORD(textPtr) + tokenOffset - 1); { the character just BEFORE the token }
- leftChar := leftPtr^;
- IF leftChar = asciiCR THEN leftKind := kCR
- ELSE IF leftChar = asciiComma THEN leftKind := kComma
- ELSE IF leftChar = asciiSpace THEN leftKind := kSpace
- ELSE leftKind := kOther;
- END;
-
- { now the char to the right }
- IF tokenOffset + tokenLength = textLength THEN rightKind := kNoChar
- ELSE
- BEGIN
- rightPtr := Ptr(ORD(textPtr) + tokenOffset + tokenLength); { the character just AFTER }
- rightChar := rightPtr^;
- IF rightChar = asciiCR THEN rightKind := kCR
- ELSE IF rightChar = asciiComma THEN rightKind := kComma
- ELSE IF rightChar = asciiSpace THEN rightKind := kSpace
- ELSE rightKind := kOther;
- END;
-
- { now classify by pairs }
- textKind := cChar; { the default }
-
- CASE rightKind OF
-
- kNoChar:
- CASE leftKind OF
- kNoChar: textKind := cChar;{textKind := kAll;} { a special case } { **CHECK HANDLING OF IT NOW!** }
- kCR: textKind := cLine;
- kComma: textKind := cItem;
- kSpace: textKind := cWord; { maybe }
- END;
-
- kCR:
- CASE leftKind OF
- kNoChar: textKind := cLine;
- kCR: textKind := cLine;
- END;
-
- kComma:
- CASE leftKind OF
- kNoChar: textKind := cItem;
- kComma: textKind := cItem;
- END;
-
- kSpace:
- CASE leftKind OF
- kNoChar: textKind := cWord; { maybe }
- kSpace: textKind := cWord; { maybe }
- END;
-
- END; { of CASE rightKind }
-
- IF textKind = cWord THEN
- BEGIN
- { your first and last chars must be non-spaces and non-CRs }
- { in order for you to be a word or range thereof }
- firstChar := Ptr(ORD(textPtr) + tokenOffset)^;
- lastChar := Ptr(ORD(textPtr) + tokenOffset + tokenLength - 1)^;
- IF (firstChar = asciiSpace) | (firstChar = asciiCR) | (lastChar = asciiSpace) | (lastChar = asciiCR)
- THEN textKind := cChar;
- END;
-
- { so now we know what you are, or are a range of - let's figure out your index/indices }
- { **CHECK - NOTE - we could use "first" and/or "last" if we wanted to - like "word 7 to }
- { last word", or whatever (skip it for now) }
-
- IF textKind = cChar THEN
- BEGIN
- { char or range of chars - easy }
- leftIndex := tokenOffset + 1;
- rightIndex := tokenOffset + tokenLength;
- END
-
- ELSE
- BEGIN
- { line, item, or word - not so easy }
- IF leftKind = kNoChar THEN leftIndex := 1
- ELSE
- BEGIN
- { there's chars to the left of you - let's make a token for THEM }
- leftToken.tokenClass := cText;
- leftToken.tokenWndw := tokenWndw;
- leftToken.tokenOffset := 0;
- leftToken.tokenLength := tokenOffset; { funny, inn't? }
-
- { **CHECK - HACK? }
- IF (textKind = cItem) | (textKind = cLine) THEN
- leftToken.tokenLength := leftToken.tokenLength - 1;
- { that should skip us over the preceding delimiter . . . }
-
- { now count }
- IF CatchErr( CountTextElems(leftToken,textKind,leftCount) , 21716 , myErr ) THEN GOTO 9;
- { that won't work for textKind = kAll! }
-
- leftIndex := leftCount + 1; { that's you! }
- END;
-
- IF CatchErr( CountTextElems(myToken,textKind,elemCount) , 21717 , myErr ) THEN GOTO 9;
- rightIndex := leftIndex + elemCount - 1; { that's the other side of you }
- END; { of getting indices for line, item, or word }
-
- { we now have indices for line, item, word, or char }
- IF leftIndex = rightIndex THEN
- BEGIN
- gTempBool := CatchErr( MakeObjSpecFromIndex(textKind,wndwObj,leftIndex,smartDesc) , 21718 , myErr );
- GOTO 9;
- END;
-
- IF CatchErr( MakeObjSpecFromIndex(textKind,wndwObj,leftIndex,leftDesc) , 21719 , myErr )
- THEN GOTO 9;
- IF CatchErr( MakeObjSpecFromIndex(textKind,wndwObj,rightIndex,rightDesc) , 21720 , myErr )
- THEN GOTO 9;
-
- gTempBool := CatchErr( MakeObjSpecFromRange(cChar,wndwObj,leftDesc,rightDesc,smartDesc) , 21721 , myErr );
-
- END; { WITH myToken }
-
- 9: { finish up }
-
- IF textHndl <> NIL THEN HUnlock(textHndl);
- gTempBool := CheckErr( DisposeSomeDescs(@wndwObj,@leftDesc,@rightDesc,NIL,NIL) , 21722 );
-
- SmartTokenRep := myErr;
- END; { SmartTokenRep }
-
-
- {$S QuillNew2}
- PROCEDURE StartKeyBuffering(key: CHAR; window: WindowPtr);
- { this routine is called for the first key-character event
- going into an empty buffer ("empty", here, not only means
- no characters in the buffer, it means nothing has been typed
- since the buffer was last emptied - you could get a "zero
- characters" situation with a combination of deletes and
- ordinary characters, but that's different from the buffer
- being truly empty). It sets up various values in the key
- buffer and handles the first typed char. The Delete char
- requires some special handling.
- INPUTS: key the character that's been typed
- window ptr to the window being typed into
- OUTPUTS: none
- NOTES: we may want to do some more sophisticated error-handling
- }
- BEGIN
- WITH keyBuffer DO
- BEGIN
-
- IF NOT bufEmpty THEN
- BEGIN
- { **CHECK - this is temporary }
- DoMyAlert('Trouble - StartKeyBuffering called with non-empty buffer!');
- EXIT(StartKeyBuffering);
- END;
-
- IF CheckErr( SmartMakeSelTextObj(window,bufDesc) , 22013 ) THEN EXIT(StartKeyBuffering);
-
- bufWndw := window;
- WITH DocumentPeek(window)^.docTE^^ DO
- BEGIN
- bufSelStart := selStart;
- bufSelEnd := selEnd;
- END;
-
- IF key <> CHR(kDelChar) THEN
- BEGIN
- { ordinary key }
- bufChars^^[0] := key;
- bufCharCount := 1; { offset to location for NEXT char }
- bufDelCount := 0;
- bufEmpty := FALSE;
- EXIT(StartKeyBuffering);
- END;
-
- { if we get to here, it's a Delete character }
-
- { SPECIAL RULE: if the original selection is non-empty, then don't count }
- { the Delete - in this case only the selection is deleted, but no chars }
- { before it. But if the selection is empty, we have to count the Delete }
- { so we can erase the char preceding the empty selection (the insertion pt). }
- { This rule only applies when a Delete is the first char typed into the buffer. }
-
- IF bufSelStart = bufSelEnd THEN bufDelCount := 1 ELSE bufDelCount := 0;
- bufCharCount := 0;
- bufEmpty := FALSE;
- END; { of WITH keyBuffer }
- END; { StartKeyBuffering }
-
-
- {$S QuillNew }
- FUNCTION StrToTextDesc(srcStr: Str255; VAR textDesc: AEDesc): OSErr;
- { this routine takes a Pascal string and converts it into a
- descriptor of type text
- INPUTS: srcStr Pascal string to be converted
- textDesc return VAR for descriptor
- OUTPUTS: error code (noErr if none)
- ERRORS:
- SIDE EFFECTS:
- NOTES: if the call returns noErr, then it returns in textDesc
- a valid descriptor that the caller is responsible for
- disposing. If it returns an error, the textDesc is undefined
- and doesn't have to be disposed
- }
- LABEL 9;
- VAR myErr: OSErr;
- srcPtr: Ptr;
- srcLen: Size;
- BEGIN
- myErr := genericErr;
-
- srcPtr := Ptr(ORD4(@srcStr)+1);
- srcLen := length(srcStr);
-
- IF CatchErr( AECreateDesc(typeChar,srcPtr,srcLen,textDesc) , 9113 , myErr )
- THEN GOTO 9; { set function result }
-
- { everything fine }
- myErr := noErr;
-
- 9: { set function result }
- StrToTextDesc := myErr;
- END; { StrToTextDesc }
-
- {$S QuillNew2}
- FUNCTION StyleDescToStyleSets(styleDesc: AEDesc; VAR onStyles: Style;
- VAR offStyles: Style; checkStyles: BOOLEAN): OSErr;
- { this routine takes an AE desc of typeTextStyles and returns
- two style sets (QuickDraw type Style) corresponding to the
- "on styles" field and "off styles" field of the descriptor.
- There is also some optional error-checking on the validity
- of the desc.
- INPUT: styleDesc a descriptor of typeTextStyles
- onStyles return VAR for the set of all styles in the "on list" field
- offStyles return VAR for the set of all styles in the "off list" field
- checkStyles if TRUE, abort if myStyles has invalid data; if FALSE, do not check
- OUTPUTS: error code (noErr if none)
- NOTES: (1) this only handles typeTextStyles, not single style items or lists of
- style items; those types should be translated/coerced into typeTextStyles
- before they get here
- (2) if checkStyles is TRUE, the following conditions are checked:
- (a) for both the "on" list and the "off" list in styleDesc, all of
- the items should be style item constants - kAEBold, kAEUnderline, etc.,
- including possibly kAEPlain. (ListToStyleSet does this check.)
- (b) kAEPlain should not be in the "off" list.
- (c) No style item constant can be in both lists.
- }
- LABEL 9;
- VAR myErr: OSErr;
- stylRec: AEDesc;
- offList: AEDesc;
- plainFlag: BOOLEAN;
- onList: AEDesc;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@stylRec,@offList,@onList,NIL,NIL);
-
- { make it a record }
- IF CatchErr( AECoerceDesc(styleDesc,typeAERecord,stylRec) , 22213 , myErr ) THEN GOTO 9;
-
- { get the "off list" out }
- IF CatchErr( AEGetKeyDesc(stylRec,keyAEOffStyles,typeAEList,offList) , 22215 , myErr ) THEN
- GOTO 9;
-
- { turn it into a style set }
- IF CatchErr( ListToStyleSet(offList,offStyles,plainFlag,checkStyles) , 22216 , myErr )
- THEN GOTO 9;
-
- { check for Plain - shouldn't appear in offList }
- IF checkStyles & plainFlag THEN
- BEGIN
- gTempBool := CatchErr( errAEBadData , 22217 , myErr );
- GOTO 9;
- END;
-
- { now get the "on list" }
- IF CatchErr( AEGetKeyDesc(stylRec,keyAEOnStyles,typeAEList,onList) , 22218 , myErr ) THEN
- GOTO 9;
-
- { turn it into a style set }
- IF CatchErr( ListToStyleSet(onList,onStyles,plainFlag,checkStyles) , 22219 , myErr )
- THEN GOTO 9;
-
- { special-case plain - in onList, it overrides everything else }
- IF plainFlag THEN
- BEGIN
- onStyles := [];
- offStyles := gAllStyles;
- GOTO 9;
- END;
-
- { check overlap }
- IF checkStyles & (onStyles*offStyles <> []) THEN gTempBool := CatchErr( errAEBadData , 22220 , myErr );
-
- 9:
- IF myErr <> noErr THEN
- BEGIN
- { just for neatness }
- onStyles := [];
- offStyles := [];
- END;
-
- gTempBool := CheckErr( DisposeSomeDescs(@stylRec,@offList,@onList,NIL,NIL) , 22221 );
-
- StyleDescToStyleSets := myErr;
- END; { StyleDescToStyleSets }
-
- {$S QuillNew2}
- FUNCTION StyleSetsToStyleDesc(onStyles: Style; offStyles: Style; VAR styleDesc: AEDesc;
- checkStyles: BOOLEAN; usePlain: BOOLEAN): OSErr;
- { this routine takes two sets of text styles (each set of QD type Style) - an
- "on" set and an "off" set - and creates a corresponding descriptor of
- typeTextStyles. Easy enough.
-
- In the case of Plain - that is, the "on" styles are empty and the "off" styles
- are EVERYTHING - the "on" list in the returned desc will either be empty (if the
- usePlain parameter is FALSE) or will contain the single item kAEPlain (if the usePlain
- parameter is TRUE). This is because I can't decide right now which one I want. In
- either case the "off" list will contain all legitimate styles.
-
- There's some optional error checking: if checkStyles is TRUE, then the routine
- will abort if there are any style items in both the "on" styles and the "off"
- styles.
-
- INPUTS: onStyles set of styles to go in the "on" list
- offStyles set of styles to go in the "off" list
- stylesDesc return VAR for desc of typeTextStyles
- checkStyles if TRUE, return error if "on" and "off"
- styles overlap; if FALSE, ignore that condition
- usePlain boolean that controls format of styles desc in
- Plain case (see above)
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- styleRec: AEDesc;
- onList: AEDesc;
- offList: AEDesc;
- thisItem: DescType;
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@styleDesc,@styleRec,@onList,@offList,NIL);
-
- IF checkStyles & (onStyles*offStyles <> []) THEN
- BEGIN
- gTempBool := CatchErr( errAEBadData , 22513 , myErr );
- GOTO 9;
- END;
-
- { create record for text styles desc }
- IF CatchErr( AECreateList(NIL,0,TRUE,styleRec) , 22514 , myErr ) THEN GOTO 9;
-
-
- { create list for "off" }
- IF CatchErr( StyleSetToList(offStyles,offList) , 22515 , myErr ) THEN GOTO 9;
-
- { create list for "on" }
- IF CatchErr( StyleSetToList(onStyles,onList) , 22516 , myErr ) THEN GOTO 9;
-
- { see if we have to append kAEPlain to "on" list }
- IF usePlain & (onStyles = []) & (offStyles = gAllStyles) THEN
- BEGIN
- { yes, we do }
- thisItem := kAEPlain;
- IF CatchErr( AEPutPtr(onList,0,typeEnumerated,@thisItem,SizeOf(thisItem)) , 22517 ,
- myErr ) THEN GOTO 9;
- END;
-
- { now add the lists to the record }
- IF CatchErr( AEPutKeyDesc(styleRec,keyAEOnStyles,onList) , 22518 , myErr )
- THEN GOTO 9;
-
- IF CatchErr( AEPutKeyDesc(styleRec,keyAEOffStyles,offList) , 22519 , myErr )
- THEN GOTO 9;
-
- { and coerce the record to typeTextStyles }
- gTempBool := CatchErr( AECoerceDesc(styleRec,typeTextStyles,styleDesc) , 22520 ,
- myErr );
-
- 9:
- { we never need to dispose of styleDesc, even in the error case, because }
- { its creation is the last possible error }
-
- gTempBool := CheckErr( DisposeSomeDescs(@styleRec,@onList,@offList,NIL,NIL) , 22521 );
-
- StyleSetsToStyleDesc := myErr;
- END; { StyleSetsToStyleDesc }
-
-
- {$S QuillNew2}
- FUNCTION StyleSetToList(styleSet: Style; VAR stylList: AEDesc): OSErr;
- { this routine takes a set of text style items (QD type Style) and returns
- a corresponding list of style constants (kAEBold, kAEUnderline, etc.).
- If the style set is empty, an empty list is returned (if you want to append
- kAEPlain to it, do it elsewhere; that decision should depend two style sets -
- the "on" and the "off" - not just one).
- INPUTS: styleSet the set of style items
- stylList return VAR for list of style item constants
- OUTPUTS: error code (noErr if none)
- }
- LABEL 9;
- VAR myErr: OSErr;
- i: INTEGER;
- thisItem: DescType;
- BEGIN
- myErr := genericErr;
- stylList := gNullDesc;
-
- { create the list }
- IF CatchErr( AECreateList(NIL,0,FALSE,stylList) , 22413 , myErr ) THEN GOTO 9;
-
- { step through the style item constants }
- FOR i := 1 TO kNumOfStyles DO
- BEGIN
- IF theStyles[i].stylItem IN styleSet THEN
- BEGIN
- { it's in the set, add constant to the list }
- thisItem := theStyles[i].stylConst;
- IF CatchErr( AEPutPtr(stylList,0,typeEnumerated,@thisItem,SizeOf(thisItem)) , 22415 , myErr )
- THEN GOTO 9;
- END; { of style item in set }
-
- END; { of loop }
-
- 9:
- IF myErr <> noErr THEN
- gTempBool := CheckErr( AEDisposeDesc(stylList) , 22416 ); { only throw it away in error case }
-
- StyleSetToList := myErr;
- END; { StyleSetToList }
-
-
- {$S QuillNew }
- FUNCTION TERecToFile(teHndl: TEHandle; fileSpec: FSSpec): OSErr;
- { open the file and write the text and style info for the given
- new-style TERec into it. The file is in the "handle-list" format
- (see WriteHandlesToFile and FillHandlesFromFile), specifically:
-
- number of data blocks = 6 (2 bytes)
- size of text block (4 bytes)
- text block (variable)
- size of style record block (4 bytes)
- style record block (variable)
- size of style table block (4 bytes)
- style table block (variable)
- size of line-height table block (4 bytes)
- line-height table block (variable)
- size of null-style block (4 bytes)
- null-style block (variable)
- size of null-scrap block (4 bytes)
- null-scrap block (variable)
-
- INPUTS: teHndl handle to new-style TERec (rec includes handle to style rec)
- fileSpec FSSpec for the file
- OUTPUTS: TRUE if successful, FALSE o.w.
- ERRORS:
- SIDE EFFECTS:
- NOTES: this new version returns an OSErr instead of TRUE/FALSE;
- will replace old in due time
- }
- LABEL 8,9;
- VAR refNum: INTEGER;
- teListCount: INTEGER;
- teInfoList: ARRAY[1..6] OF Handle;
- myErr: OSErr;
- xferCount: INTEGER;
- styleHndl: TEStyleHandle;
- BEGIN
- IF CatchErr( FSpOpenDF(fileSpec,0,refNum) , 513 , myErr ) THEN GOTO 9; { set function value }
-
- IF CatchErr( SetFPos(refNum,fsFromStart,0) , 514 , myErr ) THEN GOTO 8; { must close file }
-
- teListCount := 6;
-
- teInfoList[1] := teHndl^^.hText;
- styleHndl := GetStylHandle(teHndl);
-
- IF CatchErr( MemError , 515 , myErr ) THEN GOTO 8; { old-fashioned teRec; probably we should deal with it better }
-
- teInfoList[2] := Handle(styleHndl);
- WITH styleHndl^^ DO { I'm just getting some fields out, so I shouldn't need to lock it }
- BEGIN
- teInfoList[3] := Handle(styleTab);
- teInfoList[4] := Handle(lhTab);
- teInfoList[5] := Handle(nullStyle);
- teInfoList[6] := Handle(nullStyle^^.nullScrap);
- END;
-
- gTempBool := CatchErr( WriteHandlesToFile(teListCount,@teInfoList,refNum,xferCount) ,
- 516 , myErr );
-
- 8: { close file }
- gTempBool := CatchErr( FSClose(refNum), 517 , myErr );
-
- 9: { set function value }
- TERecToFile := myErr;
- END; { TERecToFile }
-
- {$S QuillNew }
- FUNCTION TextDescToStr(textDesc: AEDesc; VAR destStr: Str255; VAR actSize: Size): OSErr;
- { this routine takes a descriptor that contains text information
- (basically, anything that can be coerced to typeChar) and copies
- the text into a Pascal string. The text will be truncated to 255
- characters, if necessary; the actual size of the original text will
- also be returned.
- INPUTS: textDesc the descriptor containing the text
- destStr return VAR for the string
- actSize return VAR for the actual text length
- OUTPUTS: error code (noErr if none). Truncation is not an error.
- ERRORS:
- SIDE EFFECTS:
- NOTES: clearly this belongs in a coercion handler
- }
- LABEL 9;
- VAR myErr: OSErr;
- destStrPtr: Ptr;
- xferSize: Size;
- BEGIN
- myErr := genericErr;
- actSize := 0;
- destStr := 'bad string';
-
- destStrPtr := Ptr(ORD4(@destStr)+1);
- IF CatchErr( MyAECoerceDescPtr(textDesc,typeChar,destStrPtr,255,actSize) ,
- 9013, myErr ) THEN GOTO 9; { set function result }
-
- xferSize := actSize;
- IF xferSize > 255 THEN xferSize := 255;
- destStrPtr := @destStr;
- destStrPtr^ := xferSize;
-
- { everything looks fine }
- myErr := noErr;
-
- 9: { set function result }
- TextDescToStr := myErr;
- END; { TextDescToStr }
-
- {$S QuillNew2}
- FUNCTION TextElemFromTextAccessor(wantClass: DescType; container: AEDesc ;
- containerClass: DescType; form: DescType; selectionData: AEDesc; VAR value: AEDesc;
- theRefCon: LongInt): OSErr;
- { NOTES: this should be combined with "FromWndw" version, and split
- up differently . . . .
- 7/1/91 BHM Added "spots". NOTE: should probably take out the 0-length
- special case now
- }
- LABEL 9;
- VAR myErr: OSErr;
- srcText: TextToken;
- actSize: Size;
- elemCount: LongInt;
- allFlag: BOOLEAN;
- zeroFlag: BOOLEAN;
- index: LongInt;
- elemText: TextToken;
- selectionRecord: AERecord;
- startText: TextToken;
- returnedType: DescType;
- stopText: TextToken;
- newOffset: LongInt;
- newLength: LongInt;
- lastStartOff: LongInt;
- lastStopOff: LongInt;
- newLastOff: LongInt;
- rangeText: TextToken;
- BEGIN
- myErr := accessorErr; { or whatever }
- InitSomeDescs(@value,@selectionRecord,NIL,NIL,NIL);
-
- { let's get the src text }
- IF CatchErr( MyAECoerceDescPtr(container,typeMyText,@srcText,SizeOf(srcText),actSize) ,
- 13713 , myErr ) THEN GOTO 9;
-
- { now, how is the element specified? }
- IF form = formAbsolutePosition THEN
- BEGIN
-
- { count the items }
- IF CatchErr( CountTextElems(srcText,wantClass,elemCount) , 13715 , myErr ) THEN GOTO 9;
-
- { get the element index }
- IF CatchErr( DecodeOrdinal(selectionData,elemCount,index,allFlag,zeroFlag) , 13716 ,
- myErr ) THEN GOTO 9;
-
- IF allFlag THEN
- BEGIN
- myErr := MakeElemList(wantClass,srcText,value);
- GOTO 9;
- END;
-
- { some particular element }
- { get the element as a text token }
- IF CatchErr( GetTextElemFromText(srcText,wantClass,index,elemText) , 13717 , myErr )
- THEN GOTO 9;
-
- { return it in a descriptor }
- gTempBool := CatchErr( AECreateDesc(typeMyText,@elemText,SizeOf(elemText),value) , 13725 , myErr );
- GOTO 9;
- END; { of formAbsolutePosition }
-
-
- IF form = formRange THEN
- BEGIN
- { coerce the selection data into an AERecord }
- IF CatchErr( AECoerceDesc(selectionData,typeAERecord,selectionRecord) , 13719 , myErr )
- THEN GOTO 9;
-
- { get the start object as a text token }
- IF CatchErr( AEGetKeyPtr(selectionRecord,keyAERangeStart,typeMyText,returnedType,
- @startText,SizeOf(startText),actSize) , 13720 , myErr ) THEN GOTO 9;
-
- { now the stop object }
- IF CatchErr( AEGetKeyPtr(selectionRecord,keyAERangeStop,typeMyText,returnedType,
- @stopText,SizeOf(stopText),actSize) , 13721 , myErr ) THEN GOTO 9;
-
- WITH startText DO
- BEGIN
- { the windows have to be the same }
- { **CHECK on role of actual containers here, which may only be part of window }
- IF (tokenWndw <> stopText.tokenWndw) | (tokenWndw <> srcText.tokenWndw) THEN
- BEGIN
- gTempBool := CatchErr( errAECorruptData , 13722 , myErr ); { or whatever }
- GOTO 9;
- END;
- { the definition we're using for "range" right now }
- { is "from the left-most character in either of the }
- { two boundary objects to the right-most etc." We }
- { may want to reconsider this later - **CHECK }
-
- { **SPECIAL CASE for "0-length ranges" - if the second token's last }
- { char is just to the left of the first token's first char }
-
- IF tokenOffset = stopText.tokenOffset + stopText.tokenLength THEN
- BEGIN
- newOffset := tokenOffset;
- newLength := 0;
- END
- ELSE
- BEGIN
- { get some values for the new text token }
- IF tokenOffset < stopText.tokenOffset THEN newOffset := tokenOffset
- ELSE newOffset := stopText.tokenOffset;
-
- { we'll need offsets to last chars in each }
- lastStartOff := tokenOffset + tokenLength - 1;
- lastStopOff := stopText.tokenOffset + stopText.tokenLength - 1;
-
- IF lastStopOff > lastStartOff THEN newLastOff := lastStopOff
- ELSE newLastOff := lastStartOff;
-
- newLength := newLastOff - newOffset + 1;
- END;
- END; { of WITH startText }
-
- { now make the new text token }
- WITH rangeText DO
- BEGIN
- tokenClass := wantClass; { **CHECK if the wantClass should affect the calculations above }
- tokenWndw := srcText.tokenWndw;
- tokenOffset := newOffset;
- tokenLength := newLength;
- END;
-
- { and return it in a descriptor }
- gTempBool := CatchErr( AECreateDesc(typeMyText,@rangeText,SizeOf(rangeText),value) , 13723 , myErr );
- GOTO 9;
- END; { of formRange }
-
-
- { unsupported naming form }
- gTempBool := CatchErr( errAEWrongDataType , 13718 , myErr );
-
- 9: { finish up }
- gTempBool := CheckErr( AEDisposeDesc(selectionRecord) , 13724 );
-
- TextElemFromTextAccessor := myErr;
- END; { TextElemFromTextAccessor }
-
- {$S QuillNew2}
- FUNCTION TextElemFromWndwAccessor(wantClass: DescType; container: AEDesc ;
- containerClass: DescType; form: DescType; selectionData: AEDesc; VAR value: AEDesc;
- theRefCon: LongInt): OSErr;
- { NOTES: variable use here needs to be optimized, and in fact the routine
- should probably be split up based on form
- 7/1/91 BHM Added "spots". NOTE: should probably take out the 0-length
- special case now
- }
- LABEL 9;
- VAR myErr: OSErr;
- window: WindowPtr;
- actSize: Size;
- index: LongInt;
- wndwText: TextToken;
- elemText: TextToken;
- selectionRecord: AERecord;
- startText: TextToken;
- returnedType: DescType;
- stopText: TextToken;
- newOffset: LongInt;
- newLength: LongInt;
- lastStartOff: LongInt;
- lastStopOff: LongInt;
- newLastOff: LongInt;
- rangeText: TextToken;
- allFlag: BOOLEAN;
- zeroFlag: BOOLEAN;
- elemCount: LongInt;
- BEGIN
- myErr := accessorErr; { or whatever }
- InitSomeDescs(@value,@selectionRecord,NIL,NIL,NIL);
-
- { let's get the actual window }
- IF CatchErr( MyAECoerceDescPtr(container,typeMyWndw,@window,SizeOf(window),actSize) ,
- 13613 , myErr ) THEN GOTO 9;
-
- { now, how is the element specified? }
- IF form = formAbsolutePosition THEN
- BEGIN
- { make a text token representing the window's text }
- MakeTextTokenForWndw(window,wndwText);
-
- { count the items }
- IF CatchErr( CountTextElems(wndwText,wantClass,elemCount) , 13626 , myErr ) THEN GOTO 9;
-
- { get the element index }
- IF CatchErr( DecodeOrdinal(selectionData,elemCount,index,allFlag,zeroFlag) , 13627 ,
- myErr ) THEN GOTO 9;
-
- IF allFlag THEN
- BEGIN
- myErr := MakeElemList(wantClass,wndwText,value);
- GOTO 9;
- END;
-
- { some particular element }
- { get the element as a text token }
- IF CatchErr( GetTextElemFromText(wndwText,wantClass,index,elemText) , 13617 , myErr )
- THEN GOTO 9;
-
- { return it in a descriptor }
- gTempBool := CatchErr( AECreateDesc(typeMyText,@elemText,SizeOf(elemText),value) , 13618 , myErr );
- GOTO 9;
- END; { of formAbsolutePosition }
-
- IF form = formRange THEN
- BEGIN
- { coerce the selection data into an AERecord }
- IF CatchErr( AECoerceDesc(selectionData,typeAERecord,selectionRecord) , 13620 , myErr )
- THEN GOTO 9;
-
- { get the start object as a text token }
- IF CatchErr( AEGetKeyPtr(selectionRecord,keyAERangeStart,typeMyText,returnedType,
- @startText,SizeOf(startText),actSize) , 13621 , myErr ) THEN GOTO 9;
-
- { now the stop object }
- IF CatchErr( AEGetKeyPtr(selectionRecord,keyAERangeStop,typeMyText,returnedType,
- @stopText,SizeOf(stopText),actSize) , 13622 , myErr ) THEN GOTO 9;
-
- WITH startText DO
- BEGIN
- { the windows have to be the same }
- { **CHECK on role of actual containers here, which may only be part of window }
- IF (tokenWndw <> stopText.tokenWndw) | (tokenWndw <> window) THEN
- BEGIN
- gTempBool := CatchErr( errAECorruptData , 13623 , myErr ); { or whatever }
- GOTO 9;
- END;
- { the definition we're using for "range" right now }
- { is "from the left-most character in either of the }
- { two boundary objects to the right-most etc." We }
- { may want to reconsider this later - **CHECK }
-
- { **SPECIAL CASE for "0-length ranges" - if the second token's last }
- { char is just to the left of the first token's first char }
-
- IF tokenOffset = stopText.tokenOffset + stopText.tokenLength THEN
- BEGIN
- newOffset := tokenOffset;
- newLength := 0;
- END
- ELSE
- BEGIN
- { get some values for the new text token }
- IF tokenOffset < stopText.tokenOffset THEN newOffset := tokenOffset
- ELSE newOffset := stopText.tokenOffset;
-
- { we'll need offsets to last chars in each }
- lastStartOff := tokenOffset + tokenLength - 1;
- lastStopOff := stopText.tokenOffset + stopText.tokenLength - 1;
-
- IF lastStopOff > lastStartOff THEN newLastOff := lastStopOff
- ELSE newLastOff := lastStartOff;
-
- newLength := newLastOff - newOffset + 1;
- END;
- END; { of WITH startText }
-
- { now make the new text token }
- WITH rangeText DO
- BEGIN
- tokenClass := wantClass; { **CHECK if the wantClass should affect the calculations above }
- tokenWndw := window;
- tokenOffset := newOffset;
- tokenLength := newLength;
- END;
-
- { and return it in a descriptor }
- gTempBool := CatchErr( AECreateDesc(typeMyText,@rangeText,SizeOf(rangeText),value) , 13624 , myErr );
- GOTO 9;
- END; { of formRange }
-
- { unsupported naming form }
- gTempBool := CatchErr( errAEWrongDataType , 13619 , myErr );
-
- 9: { finish up }
- gTempBool := CheckErr( AEDisposeDesc(selectionRecord) , 13625 );
-
- TextElemFromWndwAccessor := myErr;
- END; { TextElemFromWndwAccessor }
-
- {$S QuillNew2}
- FUNCTION TextToIntlText(textDesc: AEDesc; scrptCode: ScriptCode; lngCode: LangCode;
- VAR intlTextDesc: AEDesc): OSErr;
- { boring subroutine. Given a text desc, along with a script code and language code,
- return a corresponding intl text desc (of typeIntlText)
- INPUTS: textDesc the text
- scrptCode the script code
- lngCode the language code
- intlTextDesc return VAR for the intl text desc
- OUTPUTS: error code (noErr if none)
- NOTES: **CHECK - could I just make my own AEDesc, starting with a NewHandle,
- or do I have to let the AEM do it (which I do here, but it looks like
- unnecessary duplicating)?
- }
- LABEL 9;
- VAR myErr: OSErr;
- myHndl: Handle;
- textLen: LongInt;
- myPtr: Ptr;
- nextPtr: Ptr;
- BEGIN
- myErr := genericErr;
- myHndl := NIL;
- intlTextDesc := gNullDesc;
-
- textLen := GetHandleSize(textDesc.dataHandle);
-
- myHndl := NewHandle(textLen + 4);
- IF CatchErr( MemError , 23513 , myErr ) THEN GOTO 9;
-
- HLock(myHndl);
- myPtr := myHndl^;
- IntegerPtr(myPtr)^ := scrptCode; { set the script code }
-
- nextPtr := Ptr(ORD(myPtr) + 2);
- IntegerPtr(myPtr)^ := lngCode; { set the language code }
-
- nextPtr := Ptr(ORD(nextPtr) + 2);
-
- { now pour the text in }
- IF CatchErr( MyAECoerceDescPtr(textDesc,typeChar,nextPtr,textLen,gActSize) , 23514 ,
- myErr ) THEN GOTO 9;
-
- { now create a descriptor for the intl text }
- gTempBool := CatchErr( AECreateDesc(typeIntlText,myPtr,textLen+4,intlTextDesc) , 23515 , myErr );
-
- 9:
- IF myHndl <> NIL THEN DisposHandle(myHndl);
-
- TextToIntlText := myErr;
- END; { TextToIntlText }
-
- {$S QuillNew2}
- FUNCTION TextTokenToDesc(srcText: TextToken; VAR dstDesc: AEDesc): OSErr;
- { given a text token, create a descriptor of typeChar that contains the
- text (just the bytes, no style info)
- INPUTS: srcText the text token
- dstDesc return VAR for text descriptor
- OUTPUTS: error code (noErr if none)
- NOTES:
- 02/17/92 BHM completely rewritten to NOT depend on MakeStylTextDesc
- (a silly and potentially recursive situation); based on
- VERY old (and anachronistically named) GetTextProp, which
- this now replaces
- }
- VAR myErr: OSErr;
- textHndl: Handle;
- textLength: LongInt;
- textPtr: Ptr;
- BEGIN
- myErr := genericErr;
- dstDesc := gNullDesc;
-
- WITH DocumentPeek(srcText.tokenWndw)^.docTE^^ DO
- BEGIN
- textHndl := hText;
- textLength := teLength;
- END;
-
- WITH srcText DO
- BEGIN
- hLock(textHndl);
- textPtr := Ptr(ORD(textHndl^) + tokenOffset);
- myErr := AECreateDesc(typeChar,textPtr,tokenLength,dstDesc);
- HUnlock(textHndl);
- gTempBool := CheckErr( myErr , 15713 );
- END;
-
- TextTokenToDesc := myErr;
- END; { TextTokenToDesc }
-
- {$S QuillNew2}
- FUNCTION WindowIsDirty(window: WindowPtr): BOOLEAN;
- { return TRUE if the window is dirty , FALSE if it's clean
- INPUTS: window ptr to the window
- OUTPUTS: TRUE if the window is dirty, FALSE if it's clean
- }
- BEGIN
- WindowIsDirty := DocumentPeek(window)^.dirtyFlag;
- END; { WindowIsDirty }
-
-
- {$S QuillNew2}
- FUNCTION WndwFromNullAccessor(wantClass: DescType; container: AEDesc ;
- containerClass: DescType; form: DescType; selectionData: AEDesc; VAR value: AEDesc;
- theRefCon: LongInt): OSErr;
- { 08/26/91 BHM Changed to handle cDocument as well as cWindow }
- LABEL 8,9;
- VAR myErr: OSErr;
- finalType: DescType;
- actSize: Size;
- nameStr: Str255;
- window: WindowPtr;
- index: LongInt;
- allFlag: BOOLEAN;
- zeroFlag: BOOLEAN;
- BEGIN
- myErr := accessorErr; { or whatever }
- value := gNullDesc;
-
- { do some checking for robustness' sake }
-
- { should only be called with wantClass = cWindow or cDocument }
- IF wantClass = cWindow THEN finalType := typeMyWndw
- ELSE IF wantClass = cDocument then finalType := typeMyDoc
- ELSE
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 1913 , myErr );
- GOTO 9; { finish up }
- END;
-
- { should only be called with containerClass = cNull }
- IF containerClass <> cNull THEN
- BEGIN
- gTempBool := CatchErr( errAEWrongDataType , 1914 , myErr );
- GOTO 9; { finish up }
- END;
-
- IF form = formName THEN
- BEGIN
- { object by name - get the name into a Pascal string }
- IF CatchErr( TextDescToStr(selectionData,nameStr,actSize) , 1915 , myErr )
- THEN GOTO 9;
-
- { check length - we'll throw it out if original text was too long }
- IF actSize > 255 THEN
- BEGIN
- gTempBool := CatchErr( errAECoercionFail , 1916 , myErr );
- GOTO 9;
- END;
-
- { see if there's a window with this name }
- window := WndwPtrFromName(nameStr);
- IF window = NIL THEN GOTO 9
- ELSE GOTO 8; { got a valid window }
- END; { of form = formName }
-
- IF form = formAbsolutePosition THEN
- BEGIN
- IF CatchErr( DecodeOrdinal(selectionData,CountWindows,index,allFlag,zeroFlag) , 1920 , myErr )
- THEN GOTO 9;
-
- { we'll ignore the zeroFlag here; the condition will be caught when we try to get the ptr }
-
- IF allFlag THEN
- BEGIN
- myErr := MakeWindowList(value,finalType);
- GOTO 9;
- END;
-
- { some particular window - does it exist? }
- window := WndwPtrFromIndex(index);
- IF window = NIL THEN
- BEGIN
- { no such window }
- myErr := errAENoSuchObject;
- GOTO 9;
- END;
-
- GOTO 8; { got a valid wndw ptr }
- END; { formAbsolutePosition }
-
- { unsupported naming form }
- gTempBool := CatchErr( errAEWrongDataType , 1918 , myErr );
- GOTO 9;
-
- 8: { got valid window - make a token to return }
- IF CatchErr( AECreateDesc(finalType,@window,SizeOf(window),value) , 1919 , myErr ) THEN GOTO 9; { couldn't make the token }
-
- { everything looks fine to me }
- myErr := noErr;
-
- 9: { set function result }
- WndwFromNullAccessor := myErr;
- END; { WndwFromNullAccessor }
-
- {$S QuillNew2}
- FUNCTION WndwPtrFromIndex(index: INTEGER): WindowPtr;
- { returns a ptr to the window with the given index
- (front window is 1, behind that is 2, etc.). If
- there's no window with that index (inc. no windows
- at all), returns NIL.
- INPUTS: index the index
- OUTPUTS: ptr to the window (NIL if no such window)
- ERRORS:
- SIDE EFFECTS:
- }
- VAR i: INTEGER;
- window: WindowPtr;
- BEGIN
- WndwPtrFromIndex := NIL;
- i := 0;
- window := FrontWindow;
- { iterate through windows }
- WHILE window <> NIL DO
- BEGIN
- i := i+1;
- IF i = index THEN
- BEGIN
- { found it }
- WndwPtrFromIndex := window;
- EXIT(WndwPtrFromIndex);
- END;
- window := WindowPtr(WindowPeek(window)^.nextWindow);
- END;
- END; { WndwPtrFromIndex }
-
- {$S QuillNew2}
- FUNCTION WndwPtrFromName(name: Str255): WindowPtr;
- { returns a ptr to the (or, the first) window with
- the given name. If there's no window with that
- name (inc. no windows at all), returns NIL.
- INPUTS: name the name
- OUTPUTS: ptr to the window (NIL if not enough windows)
- ERRORS:
- SIDE EFFECTS:
- NOTES: the name is treated as case-insensitive and
- diacritical-sensitive
- }
- VAR window: WindowPtr;
- windTitle: Str255;
- BEGIN
- WndwPtrFromName := NIL;
- window := FrontWindow;
- { iterate through windows }
- WHILE window <> NIL DO
- BEGIN
- GetWTitle(window,windTitle);
- IF EqualString(windTitle,name,FALSE,TRUE) THEN { ignore case, don't ignore diacriticals }
- BEGIN
- { found it }
- WndwPtrFromName := window;
- EXIT(WndwPtrFromName);
- END;
- window := WindowPtr(WindowPeek(window)^.nextWindow);
- END;
- END; { WndwPtrFromName }
-
- {$S QuillNew2}
- FUNCTION WriteHandlesToFile(listCount: INTEGER;
- listPtr: HandleListPtr; refNum: INTEGER; VAR xferCount: INTEGER): OSErr;
- { this routine doesn't REALLY write handles to a file; it writes the contents
- of the handles, along with their sizes, to the file. The file format is
-
- number of handles to be written INTEGER (2 bytes)
- size of first handle LongInt (4 bytes)
- contents of first handle variable
- size of second handle LongInt (4 bytes)
- contents of second handle variable
- etc.
-
- The list of handles is given by a count and a ptr to the list. The file
- must already be open and is specified by its refNum. The routine does not
- close the file. It returns an error num, noErr if there was none. It also
- returns (in the VAR parameter xferCount) the number of handles that were
- successfully written out. If that's less than listCount (due to some file
- error or whatever), WriteHandlesToFile does not correct the "number of
- handles" value at the beginning of the file; the calling routine may do
- that if it wants to. If we couldn't even write out the list count, we
- return -1 in xferCount.
-
- INPUTS: listCount number of handles in list
- listPtr ptr to list of handles
- refNum refNum of file
- xferCount return VAR for number handles written
- (-1 if we couldn't write the list count)
- OUTPUTS: error number (noErr if everything went all right)
- ERRORS:
- SIDE EFFECTS: all handles leave this routine unlocked
- }
- LABEL 8;
- VAR sizeLength: LongInt;
- myErr: OSErr;
- i: INTEGER;
- dataHndl: Handle;
- dataSize: LongInt;
- BEGIN
- { first, write the list count }
- sizeLength := SizeOf(listCount); { 2 bytes, but we needed it in a var }
- IF CatchErr( FSWrite(refNum,sizeLength,@listCount) , 1313 , myErr ) THEN
- BEGIN
- xferCount := -1; { we couldn't even transfer the list count }
- WriteHandlesToFile := myErr;
- EXIT(WriteHandlesToFile);
- END;
-
- { if you get here, myErr has already been set to noErr }
- FOR i := 1 to listCount DO
- BEGIN
- dataHndl := listPtr^[i];
- dataSize := GetHandleSize(dataHndl);
- sizeLength := SizeOf(dataSize); { 4, but we need it in a var }
- { write the length }
- IF CatchErr( FSWrite(refNum,sizeLength,@dataSize) , 1314 , myErr ) THEN
- BEGIN
- xferCount := i-1;
- GOTO 8; { leave the loop on an error }
- END;
-
- { write the data }
- HLock(dataHndl);
- myErr := FSWrite(refNum,dataSize,dataHndl^);
-
- HUnlock(dataHndl); { before checking for an error }
- { NOW check the error }
- IF CheckErr( myErr , 1315 ) THEN
- BEGIN
- xferCount := i-1;
- GOTO 8; { leave the loop on an error }
- END;
- END; { of FOR loop }
- { got through the loop okay }
- xferCount := listCount;
-
- 8:
- WriteHandlesToFile := myErr;
- END; { WriteHandlesToFile }
-
-
- {$S QuillNew2}
- FUNCTION TypeToStr(thisType: DescType): Str15;
- TYPE LongPtr = ^LongInt;
- VAR myStr: Str15;
- myPtr: Ptr;
- BEGIN
- myPtr := @myStr;
- myPtr^ := 4;
- myPtr := Ptr(ORD(myPtr)+1);
- LongPtr(myPtr)^ := LongInt(thisType);
- TypeToStr := myStr;
- END;
-
- {$S Main}
- PROCEDURE ShowObj(theObjSpec: AEDesc);
- LABEL 9;
- VAR myClass: DescType;
- myCont: AEDesc;
- myKeyForm: AEKeyword;
- myKeyData: AEDesc;
- myStr: Str255;
- BEGIN
- InitSomeDescs(@myCont,@myKeyData,NIL,NIL,NIL);
- myStr := 'bad obj';
- IF CheckErr( GetObjSpecFields(theObjSpec,myClass,myCont,myKeyForm,myKeyData) , 12113 )
- THEN GOTO 9;
- myStr := Concat('class: ',TypeToStr(myClass),'; keyform: ',TypeToStr(myKeyForm),
- '; conType: ',TypeToStr(myCont.descriptorType),'; datType: ',TypeToStr(myKeyData.descriptorType));
- 9:
- DoMyAlert(myStr);
- IF myCont.descriptorType = typeObjectSpecifier THEN ShowObj(myCont);
- gTempBool := CheckErr( DisposeSomeDescs(@myCont,@myKeyData,NIL,NIL,NIL) , 12114 );
- END; { ShowObj }
-
- {$S QuillNew2}
- FUNCTION StyleToStr(theStyle: Style): Str255;
- VAR styleName: ARRAY[1..kNumOfStyles] OF Str15;
- myStr: Str255;
- i: INTEGER;
- BEGIN
- styleName[1] := 'bold';
- styleName[2] := 'italic';
- styleName[3] := 'underline';
- styleName[4] := 'outline';
- styleName[5] := 'shadow';
- styleName[6] := 'condense';
- styleName[7] := 'extend';
-
- myStr := '';
-
- FOR i := 1 To kNumOfStyles DO
- BEGIN
- IF theStyles[i].stylItem IN theStyle THEN
- BEGIN
- IF myStr <> '' THEN myStr := Concat(myStr,',');
- myStr := Concat(myStr,styleName[i]);
- END;
- END;
-
- StyleToStr := myStr;
- END; { StyleToStr }
-
- {$S QuillNew2}
- FUNCTION MyGetErrorDesc(VAR result: DescPtr): OSErr;
- BEGIN
- result := @gErrorDesc;
- MyGetErrorDesc := noErr;
- END; { MyGetErrorDesc }
-
- {$S QuillNew2}
- PROCEDURE ShowEventAttrs(theAppleEvent: AppleEvent);
- LABEL 9;
- VAR eClass: DescType;
- eID: DescType;
- BEGIN
- IF CheckErr( AEGetAttributePtr(theAppleEvent,keyEventClassAttr,typeType,gReturnedType,
- @eClass,SizeOf(eClass),gActSize) , 23913 ) THEN GOTO 9;
-
- IF CheckErr( AEGetAttributePtr(theAppleEvent,keyEventIDAttr,typeType,gReturnedType,
- @eID,SizeOf(eID),gActSize) , 23914 ) THEN GOTO 9;
-
- DoMyAlert(Concat('class: ',TypeToStr(eClass),'; ID: ',TypeToStr(eID)));
-
- 9:
- END;
-
- {$S QuillNew}
- FUNCTION HandleWild(theAppleEvent: AppleEvent; reply: AppleEvent;
- handlerRefCon: LongInt): OSErr;
- BEGIN
- ShowEventAttrs(theAppleEvent);
- HandleWild := noErr;
- END;
-
- {$S QuillNew2}
- FUNCTION QuietGetSingularData(srcDesc: AEDesc; reqType: DescType; VAR dataDesc: AEDesc): OSErr;
- { IMPORTANT NOTE: this is EXACTLY like GetSingularData, except it doesn't display any
- error dialogs. I needed it at the last moment. Clearly it represents duplicate code
- not needed in the long run. I'll fix it all up soon - BHM 02/18/92
-
- It's also a good example of how to write QUIET routines for Quill . . . .
-
- There is another problem, which is that the GetDataFromToken call, below, ISN'T
- quiet. For the purposes that I need this, it won't come up; but I'll have to
- revisit the whole issue.
-
- this routine takes a descriptor and returns it as data of a requested type.
- The input descriptor can either be raw data or an object specifier; if it's
- an object specifier, it can only resolve to a single token, not a list of
- tokens. (This is what's needed - right now, at least - for the Set Data event.)
- If the requested type is typeWildCard, we return either a duplicate of the input
- data (if it's raw data) or use the object's default data type (if it's an object).
- INPUTS: srcDesc original descriptor - can be either raw data or an object specifier
- (resolving to a single object)
- reqType requested type
- dataDesc return VAR for data to be returned
- OUTPUTS: error code (noErr if none)
- NOTES: DON'T give this a (private) token; it would probably return it as data.
- All it knows about are object specifiers and raw data.
- 01/24/92 BHM modified to use new GetDataFromToken, which takes a LIST of req types,
- rather than just one (this routine still only takes one, however, which
- we stuff into a 1-element list)
- }
- LABEL 9;
- VAR myErr: OSErr;
- newDesc: AEDesc;
- reqTypesList: AEDesc;
- notToken: BOOLEAN; { we ignore this }
- BEGIN
- myErr := genericErr;
- InitSomeDescs(@dataDesc,@newDesc,@reqTypesList,NIL,NIL);
-
- IF srcDesc.descriptorType = typeObjectSpecifier THEN
- BEGIN
- myErr := AEResolve(srcDesc,kAEIDoMinimum,newDesc);
- IF myErr <> noErr THEN GOTO 9;
-
- { stuff the req type into a 1-element list } { this isn't really necessary in the typeWildCard case . . . . }
- myErr := AECreateList(NIL,0,FALSE,reqTypesList);
- IF myErr <> noErr THEN GOTO 9;
- myErr := AEPutPtr(reqTypesList,0,typeType,@reqType,SizeOf(reqType));
- IF myErr <> noErr THEN GOTO 9;
-
- { the next step, in addition to getting data when possible, will reject lists }
- myErr := GetDataFromToken(newDesc,reqTypesList,dataDesc,notToken);
- GOTO 9;
- END;
-
- { if it gets here, it's raw data - is it even worth checking against my token types? }
- myErr := AECoerceDesc(srcDesc,reqType,dataDesc);
-
- 9: { finish up }
- gTempBool := CheckErr( DisposeSomeDescs(@newDesc,@reqTypesList,NIL,NIL,NIL) , 21016 );
-
- QuietGetSingularData := myErr;
- END; { QuietGetSingularData }
-
-
-
-
- { END OF NEW ROUTINES FOR QUILL }
-
-
- PROCEDURE _DataInit; EXTERNAL;
-
- { This routine is automatically linked in by the MPW Linker. This external
- reference to it is done so that we can unload its segment, %A5Init. }
-
-
- {$S Main}
- BEGIN { main program }
- UnloadSeg( @_DataInit ); { note that _DataInit must not be in Main! }
- MaxApplZone; { expand the heap so code segments load at the top }
- Initialize; { initialize the program }
- UnloadSeg( @Initialize ); { note that Initialize must not be in Main! }
- EventLoop; { call the main event loop }
- DestroyKeyBuffer;
- END. { main program }